线程同步 - 微妙的问题

Ida*_*dan 1 c++ multithreading synchronization thread-safety

让我有这个循环:

static a;
for (static int i=0; i<10; i++)
{
   a++;
   ///// point A
}
Run Code Online (Sandbox Code Playgroud)

到这个循环2个线程进入......

我不确定什么......如果thread1进入POINT A会发生什么,保持在那里,而THREAD2进入循环10次,但是在将第10个循环增加到10之后,在检查之前我是值,如果它小于10,则Thread1退出循环并假设增加i并再次进入循环.Thread1将增加的价值是什么(我将会看到)?它会是10还是0?

是否可以认为Thread1会将i增加到1,然后线程2将再次循环9次(并且它们可能是8,7等等......)

谢谢

moo*_*dow 5

如果i在多个线程之间共享,则所有投注都将关闭.i在另一个线程执行期间,任何线程都可以在任何点上递增(包括该线程的递增操作的中途).没有有意义的方法来推理i上述代码中的内容.不要那样做.要么给每个线程自己的副本i,要么增加和比较10个单个原子操作.


Dov*_*Dov 5

你必须意识到增量操作实际上是真的:

read the value
add 1
write the value back
Run Code Online (Sandbox Code Playgroud)

你必须问自己,如果其中两个同时发生在两个独立的线程中会发生什么:

static int a = 0;

thread 1 reads a (0)
adds 1 (value is 1)
thread 2 reads a (0)
adds 1 (value is 1)
thread 1 writes (1)
thread 2 writes (1)
Run Code Online (Sandbox Code Playgroud)

对于两个同时增量,您可以看到其中一个可能会丢失,因为两个线程都读取了预递增的值.

你给出的例子很复杂的是静态循环索引,我最初没有注意到.由于这是c ++代码,标准实现是所有线程都可以看到静态变量,因此所有线程只有一个循环计数变量.理所当然的事情是使用普通的自动变量,因为每个线程都有自己的,不需要锁定.

这意味着虽然有时你会失去增量,但你也可能获得它们,因为循环本身可能会丢失计数并迭代额外的次数.总而言之,这是不该做的一个很好的例子.