核心java中的原子问题

发布于 2024-11-08 15:38:40 字数 179 浏览 2 评论 0原文

这是 Core Java 第 8 版第 757 页的一部分

CAUTION:

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

// notatomic

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

This is a section from Core Java 8th edition Page 757

CAUTION:

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

// not atomic

I don't understand why it's not atomic. Can any one tell me why? thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

鯉魚旗 2024-11-15 15:38:40

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 只被翻转了一次!其中一项更新似乎已丢失。这就是本书试图警告你的问题。

The flipDone method is executed by the computer in three distinct steps:

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

In Java, a piece of code can potentially be invoked in multiple threads. These threads should be thought of as executing the code concurrently.

Say, memory location labeled done contains the value false initially. Consider two threads calling flipDone, resulting in the following sequence of steps:

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

The flipDone method was called twice. done went from false to true and then back again to false - as one would expect. But since the threads execute concurrently, this is not the only ordering of steps. Consider this ordering instead:

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

While the first thread is inverting the value it read, the second thread, concurrently, is reading the value. Similarly, while the first thread is writing the value to memory, the second thread is inverting the value it read. When Thread 2 finishes, the value of done will be true. Here, although flipDone was called twice, done was flipped only once! One of the updates seem to have been lost. This is the problem that the book is trying to warn you about.

墨小沫ゞ 2024-11-15 15:38:40

这里有三个步骤:

  1. 读取布尔值 done
  2. 反转步骤 1 中读取的值
  3. 将该值分配给布尔值 done

没有什么可以阻止另一个线程预执行在这一切中间清空。

There are three steps here:

  1. Read the value of the boolean done
  2. Invert the value read in step 1
  3. Assign that value to the boolean done

There's nothing to stop another thread from pre-empting in the middle of all this.

最美的太阳 2024-11-15 15:38:40

由于两个线程可能同时调用 flipDone() 方法,因此 done 变量的状态是不确定的。

Because two threads may be calling flipDone() method at the same time so the state of the done variable is indeterminate.

淡墨 2024-11-15 15:38:40

当你执行时

done = !done;

实际发生的是:

1. Get the value of done
2. Apply the not operator
3. Assign it to done

如果两个线程一起执行第一步,它们将具有相同的done值,因此它们不会改变它两次,而是只改变它一次。

例如,如果 did 最初为 true,则更改两次后您会期望它仍然为 true,但如果两个线程一起执行步骤 1,则它将为 false。

When you execute

done = !done;

What actually happens is:

1. Get the value of done
2. Apply the not operator
3. Assign it to done

If two threads execute the first step together, they are going to have the same value of done, so instead of changing it two times, they will change it only once.

For instance if done was initially true, after changing it two times you'd expect it's still true, but if the two threads execute step 1 together, it will be false.

风筝有风,海豚有海 2024-11-15 15:38:40

它不是作为单个不可分割的操作执行,而是由三个离散操作组成的序列 - 获取done的当前值、对值取反、将新值写回done。这是一个读取-修改-写入操作,其中结果状态源自先前的状态。

It does not execute as a single indivisible operation but instead is a sequence of three discrete operations - Fetch the current value of done, Negate the value, Write the new value back to done. It is a read-modify-write operation in which the resulting state is derived from the previous state.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文