我的程序基于两个共享协议对象的线程。根据共享协议对象中的布尔值,我试图让另一个线程在使用协议之前等待。
主服务器:
GameProtocol protocol = new GameProtocol();
MyThreadedClass thread1 = new MyThreadedClass(protocol);
MyThreadedClass thread2 = new MyThreadedClass(protocol);
thread1.start()
thread2.start()
螺纹类别:
GameProtocol protocol;
private MyThreadedClass(GameProtocol protocol){
this.protocol = protocol
}
private GamePackage waitCheck(GamePackage gp){
if(!gp.isWaiting()) {
return protocol.update(gp);
}
while(protocol.waitForCategory) {
//System.out.println(protocol.waitForCategory);
}
return protocol.update(gp);
}
通信协定类别:
boolean waitForCategory = false;
public synchronized GamePackage update(GamePackage gp){
if(gp.myTurnToPickCategory){
gp.setWaiting(false);
waitForCategory = true;
} else {
gp.setWaiting(true);
waitForCategory = false;
}
return gp;
}
现在我的意图是让一个线程等待,直到另一个线程第二次使用update方法。但是第二个线程在while循环中卡住了,即使布尔值waitForCategory
被设置为false。一旦我添加了System.out.println(protocol.waitForCategory);
行,它就开始工作了。如果我把它移走,它又会停止工作。我似乎不明白布尔值上的一个sout是如何使它工作的。如果有人明白这一点,有可能用另一种方法来解决它吗?因为在这样的循环中有一个sout会使它很混乱。
2条答案
按热度按时间yyhrrdl81#
Here is the explanation for why println makes the code work: stackoverflow.com/q/25425130/217324 – Nathan Hughes
6ojccjat2#
正如其他人已经解释的那样,
println()
的引入将同步插入到图片中,因此您的代码给人一种它工作的错觉。为了解决这个问题,你必须确保所有的东西都是正确同步的。换句话说,
gp.isWaiting()
也必须同步,并且protocol.waitForCategory
必须移动到一个方法中并同步。或者,停止尝试使用同步,改用通过
java.util.concurrent.BlockingQueue
的异步消息传递。您的代码将执行得更好,您将不会面临争用条件的危险,并且您的代码也将是可测试的。(而使用同步,您的代码将永远是不可测试的,因为没有任何测试会捕获争用条件。)