读取会影响线程竞赛期间的写作吗?

时间:2015-03-23 17:02:36

标签: c++ multithreading

我问这个问题是为了更好地理解C ++中的线程竞争现象(但这可能是语言无关的......?)。

假设我有两个线程,共享资源(比如int n,初始值为0)。

线程A工作一段时间,直到找到n的值,以便在某个时刻n = /* some value here */;

线程B忙等待n的值,类似于while(!n);

n将仅由线程A设置一次,不会更改。现在,当设置n时,线程A和B之间会发生竞争。但是,在这种情况下,一个线程是只写的,一个线程是只读的,所以我想知道是否实际上有可能由于竞争而没有由线程A设置n的值,因此使线程B永远挂起。

总结一个例子:

int n = 0;

void threadA()
{
   cin>>n;
}

void threadB()
{
   while(!n);
   cout<<n<<endl;
}

int main()
{
    // Run threadA and threadB as parallel threads. (Or run threadA as a thread and call threadB from the main thread).
}

当我为n输入一些值时会发生什么?

2 个答案:

答案 0 :(得分:2)

是的,线程B可以永远等待等待。原因是简单的C ++,你需要一个明确的同步&#34;握手&#34; (原子操作或同步原语,如互斥),以确保一个线程写入的值对另一个线程可见。您的代码中没有此类同步操作,因此无法保证线程B将继续运行。

完全有可能线程B将0读入缓存并且缓存线永远不会更新,因为没有理由这样做 - 没有原子或同步操作可能会强制更新。就编译器而言,线程B读取n导致未定义的行为,因此它可以安全地假设B不读取n

答案 1 :(得分:1)

根据问题中的代码,线程可能永远阻塞。

编译器/ cpu可能会查看代码cin >> n,并决定将分配优化到n(即使提示输入),因为它已检测到n赢了随后使用。即使它没有被优化掉,它也可能位于永远不会刷新到主内存的cpu缓存行中,导致其他线程永远不会看到该值。

为了避免这种情况,你应该使用原子类型(从C ++ 11开始)或者为平台使用适当的内存屏障。