我有一个“serial”类,它扩展了使用串口的线程。在run()方法中,我首先打开端口,设置所有串行参数并添加一个serialporteventlistener。然后我把一个while(go)放在其中,go是一个私有的(只有类才能看到它)布尔示例,设置为true。我有一个kill方法,它不仅关闭端口并删除serialeventlistener,还将“go”设置为false,因此线程应该停止。现在,事情开始变得奇怪了:如果我在while(go)中放置一个system.out.println(something),当我调用kill()方法时,thred停止,但如果我不这样做,它将保持活动状态。你知道为什么会这样,怎么解决吗?
while(go) {
System.out.println("in");
}
public void kill(){
go = false;
try {
this.serialPort.removeEventListener();
this.serialPort.closePort();
} catch (SerialPortException e) {
e.printStackTrace();
}
}
2条答案
按热度按时间jhdbpxl91#
我不想争论你实现这些线程的方式。然而,看看具体的场景,你有一个
Serial
类,只要变量go
是true
. 同样的变量也可以由另一个线程(即主线程)在方法完成后进行更改kill
已调用。正如@wjs所建议的,使事情正常工作的最佳方法是声明变量
go
“易失性”。你应该有这样的东西:基本上,通过这种方式,jvm确保不同的线程读取一个一致的变量值,而实际上这正是像您这样的多线程场景中发生的事情。
另一种方法是将变量go定义为
java.util.concurrent.atomic.AtomicBoolean
,而不是把它当作简单的原语boolean
. 在这种情况下,这种方法也非常有效,因为通过这种方式,jvm保证变量值的每一次更改都是原子操作,这意味着使其成为“一”,并且您将始终避免任何可能的争用条件。在这种情况下,您的代码应该是这样的:
8wigbo562#
除非
go
如果声明为volatile,则不能保证while循环(或其他任何东西)将读取当前值。宣布进入
然后它应该可以工作(除非还有其他事情没有发布)。而这样做并不能减轻进行适当同步的需求。