同步方法可以有竞争条件吗? [例]

时间:2014-04-07 21:18:29

标签: 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) {
    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; 
  }
}

微妙与否,我认为我对同步方法的作用存在根本性的误解。我的印象是他们通过使用锁令牌(或类似的)限制对线程的访问,因此永远不会竞争。那么,如果它的方法是同步的,那么这个例子如何具有竞争条件?任何人都可以帮忙澄清一下吗?

5 个答案:

答案 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()时,所有线程都被唤醒,并且它们竞争获得他们正在等待的锁,并且不可能说下一个将执行哪个。