这是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
方法被调用了两次。 done
从false
转到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
仅被翻转了一次!更新之一似乎已丢失。这是本书试图警告您的问题。