这是Core Java 8th Edition 757的一部分

警告:

public void flipDone() {
   done = !done;
}


//不是原子的

我不明白为什么它不是原子的。谁能告诉我为什么?谢谢

最佳答案

flipDone方法由计算机以三个不同的步骤执行:

Read the value of memory location labeled done into ALU
Flip the value (i.e true -> false or false -> true)
Write the new value into the memory location done


在Java中,一段代码可能会在多个线程中被调用。这些线程应被视为并发执行代码。

说,标记为done的内存位置最初包含值false。考虑两个调用flipDone的线程,导致以下步骤序列:

Thread 1                             Thread 2
-----------------------------------------------------------------------
Read value of done, false
Invert that value to true
Write the new value, true, to done
                                     Read value of done, now true
                                     Invert that value to false
                                     Write the new value, false, to done


flipDone方法被调用了两次。 donefalse转到true,然后又回到了false-正如人们所期望的那样。但是由于线程是同时执行的,所以这不是步骤的唯一顺序。请考虑以下排序:

Thread 1                             Thread 2
-----------------------------------------------------------------------
Read value of done, false
Invert that value to true            Read value of done, false
Write the new value, true, to done   Invert that value to true
                                     Write the new value, true, to done


当第一个线程正在反转其读取的值时,第二个线程同时正在读取该值。同样,当第一个线程将值写入内存时,第二个线程将其读取的值反转。 Thread 2完成后,done的值为true。在这里,尽管flipDone被调用了两次,但done仅被翻转了一次!更新之一似乎已丢失。这是本书试图警告您的问题。

10-07 19:50