【问题标题】:Untouched shared resources in C++ threadingC++ 线程中未触及的共享资源
【发布时间】:2015-05-07 11:47:03
【问题描述】:

想象以下场景:

#include <chrono>
#include <iostream>
#include <thread>
#include <vector>

void DoSomething(int* i)
{
    std::cout << *i << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    *i = 2;
    std::cout << *i << std::endl;
}

int main()
{
    std::vector<int> v = {0, 0, 0};
    v[0] = 1;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::thread t(&DoSomething, &v[0]);
    t.join();
    std::cout << v[0] << std::endl;
}

是否有任何理由应该与向量元素一起传递互斥锁?

P.D.从 2015 年 5 月 8 日起

我在发帖时没有详细说明这个问题,因为我不想影响答案。到昨天为止,您的回答几乎是我的理解。然而,有人向我建议,直觉行为可能无法像人们希望的那样在线程场景中发挥作用。特别是,在这种情况下,有人建议,例如,假设发生在主线程上的写入 v[0] = 1 是在没有互斥体的情况下将在 DoSomething 中打印时得到反映的假设不能保证。作为一种可能的解释,我被告知该值可能会进入线程可访问内存,但它可能会在写入跨线程内存之前被不同线程的状态换出,并且再次保证唯一的方法所需的传播将使用互斥锁。你对这个论点有什么看法?

【问题讨论】:

    标签: c++ multithreading mutex


    【解决方案1】:

    互斥锁用于同步多个线程之间的数据访问。如果两个或多个线程访问相同的数据,并且其中至少有一个是写入器,则它们需要同步。

    在您的情况下,DoSomething 确实会写入您传递给它的元素。但是,在您当前的示例中,执行写入的线程是当时访问该元素的 only 线程,因为主线程在随后的连接中立即被阻塞。

    如果主线程同时访问v,则需要保护该访问:

    // BROKEN CODE BELOW
    
    int main()
    {
        std::vector<int> v = {0, 0, 0};
        std::thread t(&DoSomething, &v[0]);
        // swapped the join and the cout; now cout accesses v[0] 
        // while DoSomething writes to it, which is bad;
        std::cout << v[0] << std::endl;
        t.join();
    }
    

    至于您的编辑:您基本上担心v[0] 的初始分配可能会重新排序,因此DoSomething 线程将看不到它。原则上,写入可以通过并发线程将观察到的值与直观预期不同的方式重新排序。防止这种情况的唯一方法是插入memory barriers,它显式地强制执行某种排序。在 C++ 中,这通常通过线程同步原语(如 std::mutex 或 atomics)发生。

    幸运的是,the creation of a thread acts as such a memory barrier。因此,在您的示例中,对v 的初始写入发生在线程创建之前,一切都很好,您不会遇到任何有害的重新排序。

    【讨论】:

    • 感谢您的回答。请参阅我写的问题的补充。
    • @SomeDude 我已经编辑了答案以解决您编辑的问题。
    【解决方案2】:

    没有。事实上,线程创建 + 立即连接使得这是一个有效(非常昂贵)的顺序函数调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多