我正在学习同步方法,作为防止Java中的竞争条件和不需要的行为的一种方法。我看到了以下示例,并告诉竞争条件非常微妙:
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;
}
}
微妙与否,我认为我对同步方法的作用存在根本性的误解。我的印象是他们通过使用锁令牌(或类似的)限制对线程的访问,因此永远不会竞争。那么,如果它的方法是同步的,那么这个例子如何具有竞争条件?任何人都可以帮忙澄清一下吗?
答案 0 :(得分:1)
多线程是指使用新线程(可运行).start();这将启动一个新线程并转到run()方法。 runnable是任何实现runnable的类。或者扩展线程的同步方法确保如果这些线程想要读取由synchronized方法改变的数据,那么它将是可能的,否则它可能会保持不变,或者更糟,半变化。
答案 1 :(得分:1)
我认为作者想到的是,由于count从0到2,两个线程可能会按顺序调用put()
,因此读者线程将错过其中一条消息。
这确实是竞争条件:读者和推杆竞争同一个锁,如果正在读取的消息取决于notifyAll()
通知哪个线程。
答案 2 :(得分:1)
Java的同步方法会让您在两种方法之间互斥,这意味着您可以假设它们不会交错。
但是,您仍然有竞争条件,因为您可以根据首先运行的方法获得不同的行为。
正如JB Nizet在他的回答中所建议的,考虑两个排序中的每一个都会发生什么(假设它们在不同的线程中运行)。
答案 3 :(得分:1)
考虑计数的方式&gt; 2 ...
该代码也有难闻的气味。应该计算什么?为什么要增加它并重置它?为什么不必要地使用这个&#39;?如果我在项目中看到类似的代码,我会仔细查看它非常 ...
答案 4 :(得分:0)
当两个实体竞争单个资源时会发生竞争条件,如果结果取决于订单,则可能导致不可预测的行为。当你使用notifyAll()时,所有线程都被唤醒,并且它们竞争获得他们正在等待的锁,并且不可能说下一个将执行哪个。