使用wait notify更新Java子类

使用wait notify更新Java子类,java,concurrency,wait,notify,Java,Concurrency,Wait,Notify,注意:如果此等待和通知使用了不正确的语法,请随意编辑/评论 您有一个类,该类的计算仅由不同的线程完成: class Foo{ public Foo() { //so thread 2 can know about us. So much for design patterns. synchronized(GlobalStuff) {GlobalStuff.threadpool.add(this);} } Bar b; public Bar em

注意:如果此等待和通知使用了不正确的语法,请随意编辑/评论

您有一个类,该类的计算仅由不同的线程完成:

class Foo{
   public Foo() {
      //so thread 2 can know about us. So much for design patterns.
      synchronized(GlobalStuff) {GlobalStuff.threadpool.add(this);} 
   }

   Bar b;
   public Bar emptyBar() { //called by thread #1 ("your" thread).
     synchronized(this) {
        b = new Bar();
        return b;
     }
   }
   public void makeTest() { //Thread #2 periodically runs this block of code.
      synchronized(this) {
         if (b==null) {return;} //do nothing if it is still null.
         if (b.hasBeenMadeIntoExam();) {return;} //do nothing if it is done already.

         b.makeMeAnAnnoyingExam();
         ....
         this.notifyAll(); //do we even need the "this"?
      }
   }
}
以下是您等待它的方式:

//thread 1 runs this block of code.
Foo fooey = new Foo();
Bar b = fooey.emptyBar();
while( b.equals(fooey.emptyBar()) ) { //some statement to check whether it is done or not
   try { //mandatory try catch statements to keep Java verbose.
       fooey.makeTest();
       fooey.wait(); //wait, and fooey will free us when it calls notifyAll()
   } catch (InterruptedException ex) {}
}
.... //more code that depends on the exam being made.

我担心的是b的字段不是易失性的(即使我们将b更改为易失性),所以当线程2更新它们时,它们不会立即出现在线程1中。请记住,同步和通知并不“深入”,因此它们不会仔细地更新所有子类的状态。我需要担心吗?有没有一种方法可以解决这个问题,而不用手动在每个地方粘贴“volatile”?

而不是同步整个实例。您只能同步方法

b栏; 公共同步条emptyBar(){//由线程#1(“您的”线程)调用。 b=新杆(); 返回b; }


而不是在Foo中添加
synchronized
块。您可以
同步
条中更改对象状态的方法。

我通常避免使用“this”进行同步。不要使用synchronized(这个),而是定义一个显式锁并根据该锁进行同步。如果子类需要它,那么也让它们可以使用它。例如

class Foo {

  protected final Object lock = new Object();

  public Bar emptyBar() {
    synchronized (lock) { 
      ...
    }
  }

  ...

}
使用lock.notifyAll();,而不是这个.notifyAll()


只要要读/写的所有字段都在同步(锁定)块中被访问/更新,您就可以确信这些值是最新的。

很难解释为什么多线程代码甚至无法编译。在提出问题之前,请注意代码。是的,这种方式具有更少的阻塞,因此具有更高的性能(尽管在我的真实版本中没有太大帮助)。我的方法可以按原样工作吗?你不能通过使用它作为锁对象来同步“整个类”。那时它只是另一把锁。同步较小的代码总是更好。为什么不使用这个呢?子类无法获得它?@tgkprog“this”可能会允许意外的同步作用域爬行,因为外部代码可以同步(fooInstance),这增加了在处理同步的多个监视器时引入死锁的可能性。此外,它还使得以后更容易将锁定impl从同步更改为读写锁定等其他操作,而无需担心您可能无法查看的外部代码(尤其是库)。