我写了一个简单的应用程序,它有主线程(生产者)和多个消费者线程.我想从主线程广播一条消息,所以所有的消费者线程都会收到它.
但是,我有麻烦.
我试图了解Thread.sleep如何与Happens-Before相关.这是我的一段代码:
import java.util.*;
public class PubSub {
public static void main(String[] args) {
List
如果我添加睡眠,消费者将开始接收消息:
@Override
public void run() {
while(true) {
try {
Thread.sleep(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!queue.isEmpty()) {
String message = queue.poll();
System.out.println(
getName() + ": Consuming message: " + message
);
}
}
}
由于Thread.sleep是一个本机方法,我想了解它如何解决之前发生的事情.
我必须注意,之前修复的真正方法是生成volatile关键字:
private volatile Queue
@Override
public void run() {
synchronized (queue) {
while (true) {
if (!queue.isEmpty()) {
String message = queue.poll();
System.out.println(
getName() + ": Consuming message: " + message
);
}
}
}
}
I’m trying to understand how Thread.sleep may be related to Happens-Before
在before-before和Thread.sleep之间没有任何关系. JLS明确指出Thread.sleep没有任何同步语义:
Neither a sleep for a period of zero time nor a yield operation need have observable effects.
It is important to note that neither Thread.sleep nor Thread.yield have any synchronization
semantics. In particular,the compiler does not have to flush writes cached in registers out to
shared memory before a call to sleep or yield,nor does the compiler have to reload values cached
in registers after a call to sleep or yield. For example,in the following (broken) code fragment,
assume that this.done is a non-volatile boolean field:
while (!this.done)
Thread.sleep(1000);The compiler is free to read the field this.done just once,and reuse the cached value in each execution of the loop. This would mean that the loop would never terminate,even if another thread changed the value of this.done
在相关的说明中,消费者似乎开始消费消息(在我的机器上),如果添加在while循环之后立即在运行时计算的语句.例如,添加this.toString()会导致使用者开始使用消息.
public void run() {
while(true) {
this.toString();
这仍然没有解释行为,但它进一步证实了Thread.sleep不一定是消费者突然看到对队列进行更新的原因.