Java 同步方法可以有竞争条件吗?[示例]
我正在学习将同步方法作为防止Java中的竞争条件和不必要行为的一种手段。有人向我介绍了以下示例,并告诉我比赛条件非常微妙:Java 同步方法可以有竞争条件吗?[示例],java,multithreading,race-condition,Java,Multithreading,Race Condition,我正在学习将同步方法作为防止Java中的竞争条件和不必要行为的一种手段。有人向我介绍了以下示例,并告诉我比赛条件非常微妙: public class Messages { private String message = null; private int count = 2; // invariant 0 <= count && count <= 2 public synchronized void put(String message) {
public class Messages {
private String message = null;
private int count = 2;
// invariant 0 <= count && count <= 2
public synchronized void put(String message) {
while( count < 2 )
this.wait();
this.message = message;
this.count = 0;
this.notifyAll();
}
public synchronized String getMessage() {
while( this.count == 2 )
this.wait();
String result = this.message;
this.count += 1;
this.notifyAll();
return result;
}
}
公共类消息{
私有字符串消息=null;
私有整数计数=2;
//不变0多线程是指使用新线程(runnable).start()时;这将启动一个新线程并转到run()方法。runnable是任何实现runnable的类。或扩展线程。同步方法确保,如果这些线程希望读取由同步方法更改的数据,那么它将是可能的,否则它可能会保持不变,或者更糟糕的是,更改了一半。我猜想作者想到的是,由于计数从0到2,两个线程可能依次调用put()
,因此读卡器线程将错过其中一条消息
这确实是一个竞争条件:读卡器和推杆争夺同一个锁,如果正在读取的消息取决于notifyAll()
Java的同步方法会让你在这两个方法之间互斥,这意味着你可以假设它们不会交错
但是,您仍然有一个竞争条件,因为根据首先运行哪个方法,您可以获得不同的行为
正如JB Nizet在他的回答中所建议的,考虑这两个排序中的每一个发生了什么(假设它们在不同的线程中运行)。
这段代码也有一股难闻的味道。什么是计数?为什么要递增它,然后重置它?为什么不必要地使用“this”?如果我在项目中看到这样的代码,我会非常仔细地看它…每当两个实体争夺一个资源时,就会出现竞争情况,这可能会导致不可预测的行为如果结果取决于顺序,则vior。当您使用notifyAll()时,所有线程都会被唤醒,它们会竞相获取等待的锁,并且无法确定下一个将执行哪个锁。对于这样的问题,我总是会盲目地回答“是”(仅基于标题).Ahhh,我想我明白了。顺序很重要,因为count被初始化为2,getMessage将首先执行。它的等待将释放锁,并且,当它试图获取消息时,消息将永远不会通过put加载?请用示例代码更清楚地解释一下。作为一个独立的竞态条件示例,我假设它不应该被加载太好了。我只是想分析一下。我认为你的指针是有意义的,而且似乎符合我现在的想法,基于我对另一个答案的评论!谢谢!你能详细说明一下打破OP示例的交错吗?我一直在试着找一个,因为我很好奇,我无法找到。如果两个单独的线程调用put
,则第一个将设置计数=0
,第二个将等待()
.Hmm,你说得对。@Rome\u Leader你能不能不接受这个答案,这样我就可以删除它。对不起,请用示例代码再解释一下。我不明白竞态条件是如何实现的。请用示例代码场景解释解决方案。