为什么2个线程递增一个变量会导致不同的输出

PTN*_*PTN 2 c concurrency multithreading

我刚刚开始学习并发编程,即使我对此有一个模糊的想法,为什么两个线程递增一个变量会导致不同的输出?

假设变量i是全局的,并且有两个线程试图这样做

i = i + 1;
Run Code Online (Sandbox Code Playgroud)

为什么输出可以是1还是2?假设主线程没有退出,因为我知道有可能主线程在其中一个线程能够执行任何操作之前退出.

Joh*_*pit 9

因为加法运算不是原子的.

来自维基百科:

在并发编程中,如果系统的其余部分在瞬间发生,则操作(或操作集)是原子的.

原子性是与并发进程隔离的保证.

记住这一点,请考虑以下(简化)插图.该操作i = i + 1由三个原子操作组成:

  • i从内存中读取当前值
  • 将1添加到读取的值
  • i回内存

当两个线程尝试执行时i = i + 1,它们可能都获得相同的当前值i,然后将其设置为i + 1,使其看起来只是1递增.考虑以下两种可能的情况:

场景1

int i = 0;
i = i + 1;

Thread 1: Reads i       // Reads 0
Thread 1 : i = i + 1    // Adds 1 to i
Thread 1: Write i = 1   // Makes i == 1
Thread 2: Reads i;      // Reads 1
Thread 2: i = i + 1     // Adds 1 to i, making i == 2
Thread 2: Write i = 2   // Makes i == 2

// Finally, i becomes 2
Run Code Online (Sandbox Code Playgroud)

在上面的场景中,一切都按预期工作.但是当线程2在线程1写入值之前读取时会发生什么i

情景2

int i = 0;
i = i + 1;

Thread 1: Reads i       // Reads 0
Thread 1 : i = i + 1    // Adds 1 to i
Thread 2: Reads i;      // Reads 0 - NOT 1 because it's not written to memory yet
Thread 1: Write i = 1   // Makes i == 1
Thread 2: i = i + 1     // Adds 1 to i, making i == 1 (Remember, thread 2 had read 0)
Thread 2: Write i = 1   // Makes i == 1

// i is finally 1, instead of 2
Run Code Online (Sandbox Code Playgroud)