我遇到一个问题,即两个线程正在访问共享变量而无法查看上次更改。
我有一个GUI线程,它有一个文本框,鼠标点击监听器,一旦记录一下,创建一个新的线程,将值注入文本框,当第二次鼠标点击被调用时,最后创建的线程将被停止并且将创建一个新的,也将注入值等等。
public class SomeGuiClass{
private static boolean isRunning = false;
private static boolean canRun = true;
private Thread thread;
public SomeGuiClass(){
txt.addMouseListener(new MouseListener() {
@Override
public void mouseDoubleClick(MouseEvent arg0) {
if (isRunning){
// force the thread to stop running.
canRun = false;
// waits for the thread to stop his run.
while(isRunning);
}
thread = new Thread(new Runnable() {
@Override
public void run() {
SomeGuiClass.isRunning = true;
while(SomeGuiClass.canRun){
// Inject values to text box, using Display.asyncExec...
Thread.sleep(1000);
}
SomeGuiClass.isRunning = false;
}
});
SomeGuiClass.canRun = true;
thread.start();
}
}
}
}
问题是,读取isRunning
的GUI线程无法看到新线程执行的最后一次更新,导致while(isRunning)循环永远在运行。
我尝试使用volatile,同样的事情发生了。看起来我正在做的事情在逻辑上是正确的,只缺乏关于如何丢失java内存模型的技术信息。
答案 0 :(得分:4)
几点意见:
您必须同时使isRunning
和canRun
易变,才能使其正常工作
由于您的其他线程每1000毫秒只检查canRun
,因此在处理GUI线程上的mouseDoubleClick
第二次调用之前,您可能仍有很长的延迟。
让线程忙等待
通常是一个非常糟糕的主意 while(true){/*do nothing*/}
循环。
你绝对应该使用wait/notify机制来在线程之间进行同步