我一直在试验Java线程可见性问题,通过一个共享的布尔和非易失性变量向目标线程发送一个停止信号到线程的流行示例,目标线程似乎没有得到它)如下图所示:Java线程可视性和同步
public class ThreadVisibilityTest {
//Shared variable to send a signal to the thread
static boolean stopped = false;
public static void main(String[] args) throws Exception {
Thread targetThread = new Thread(new Runnable() {
public void run() {
while(!stopped) {}
System.out.println("Target thread gets signal and stops...");
}
});
targetThread.start();
TimeUnit.SECONDS.sleep(5);
stopped=true;
System.out.println("Main thread has sent stop signal to the thread...");
}
}
主线程设置stopped
为true,目标线程无法得到它的手段在5秒后发出停止信号给目标线程,因此不会停止。
定义stopped
变量为volatile
明显解决了这个问题。
卜后来我意识到,如果我做stopped
变量non volatile
而是访问它在目标线程背景,目标线程得到最终值和停止。所以线程可见性问题似乎可以像使用volatile
来解决。
Thread targetThread = new Thread(new Runnable() {
public void run() {
while(true) {
synchronized(this) {
if(stopped) break;
}
}
System.out.println("Target thread gets signal and stops...");
}
});
而且还可以用于同步的对象监视器似乎没有任何效果如下:
synchronized(Thread.class) {
if(stopped) break;
}
这东西是偶然发生还是我错过了什么? 或者我们可以说通过互斥访问共享变量似乎强制目标线程刷新其缓存内存,就像访问变量volatile
一样吗?
如果后者是真实的你建议克服线程可见性问题,通过挥发性关键字或访问互斥?
在此先感谢
如果您知道必须使用此变量的最新值,为什么您会选择不使用易失性?你认为它有什么问题? –
如果你想使用同步,你当然必须做在相同的监视器上同步停止块的写入和读取。您不会在同步块中写入该值。 –
我不是不想选择易变的。我试图理解为什么互斥也解决了内存可见性问题,因为我已经测试并发现,通过互斥来访问共享变量会使您像volatile一样获得最终值。 – Serdar