【问题标题】:notifyall() not the last statementnotifyall() 不是最后一条语句
【发布时间】:2013-05-02 15:57:54
【问题描述】:

假设我在 Java 中有一个读/写监视器实现。

几个读者或一个作家可以在任何时候访问数据库(不能同时访问)

class RWmonitor{
   private int readers = 0;
   private boolean writing = false;

   public synchronized void StartRead(){ ..}
   public synchronized void EndRead(){ 
      notifyAll();
      readers--;
   }

   public synchronized void StartWrite(){ ..}
   public synchronized void EndWrite(){
      notifyAll();
      writing = false;
   }
}

现在,notifyAll() 不是同步方法中的最后一条语句有关系吗?

假设:

1) EndRead() 执行

2) notifyAll() 通知所有等待的线程

3) 然后它会减少读者数量。

当它执行notifyAll() 时,是否会因为被唤醒的线程等待释放 RWmonitor 上的锁而导致成本更高? (假设锁在 RWmonitor 上的线程还在readers--;

【问题讨论】:

    标签: java concurrency monitors


    【解决方案1】:

    它是否是最后一个语句并不重要。

    引用javadoc for notifyAll()

    在当前线程放弃对该对象的锁定之前,被唤醒的线程将无法继续。

    【讨论】:

    • 效率会有什么不同吗?或者会被认为可以忽略不计?
    • @ali - 理论上,在通知后尽快退出同步块可能更有效(即通知应该是最后一个操作)。
    【解决方案2】:

    不,没关系。锁将一直保持到synchronized 块结束,并且在此期间没有线程能够在锁上wait。事实上,先发出通知稍微有利一点,因为异常可能会停止更新,但不会停止通知。

    【讨论】:

    • 啊..认为异常可能会停止更新很有趣。谢谢!
    • 但是,如果更新没有发生,那么您可能一开始就不需要通知。
    • @jtahlborn 如果在通知之后但在更新之前出现异常,则线程会唤醒但绕过它们的 while 循环,这是安全的。 (尽管您可能会丢失版本。)
    • @jtahlborn 啊,但反过来,你得到了更新但没有通知,所以其他线程即使应该继续,也会卡在那里。虽然显然它与像这样的简单操作没什么区别。
    • 如果在更新过程中发生异常,那么很可能更新没有发生(至少没有完全发生)。
    猜你喜欢
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    相关资源
    最近更新 更多