我问这个问题是为了更好地理解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
输入一些值时会发生什么?
答案 0 :(得分:2)
是的,线程B可以永远等待等待。原因是简单的C ++,你需要一个明确的同步&#34;握手&#34; (原子操作或同步原语,如互斥),以确保一个线程写入的值对另一个线程可见。您的代码中没有此类同步操作,因此无法保证线程B将继续运行。
完全有可能线程B将0读入缓存并且缓存线永远不会更新,因为没有理由这样做 - 没有原子或同步操作可能会强制更新。就编译器而言,线程B读取n
导致未定义的行为,因此它可以安全地假设B不读取n
。
答案 1 :(得分:1)
根据问题中的代码,线程可能永远阻塞。
编译器/ cpu可能会查看代码cin >> n
,并决定将分配优化到n
(即使提示输入),因为它已检测到n
赢了随后使用。即使它没有被优化掉,它也可能位于永远不会刷新到主内存的cpu缓存行中,导致其他线程永远不会看到该值。
为了避免这种情况,你应该使用原子类型(从C ++ 11开始)或者为平台使用适当的内存屏障。