信号量同步wait()和notify()



我有下面的代码:这是获得信号量的知识。代码是线程A首先等待b.wait()(使调用线程睡眠),然后得到通知,为什么代码在这里同步?如果不存在,则给出IllegalMontiorXXXXXXXXX异常。

public class ThreadA {
   public static void main(String[] args){
     ThreadB b = new ThreadB();
     b.start();
     synchronized(b){
        try{
            System.out.println("Waiting for b to complete...");
            b.wait();
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("Total is: " + b.total);
    }
  }
}

class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();
        }
    }
}

编辑:答案是同步让当前线程拥有信号量。Notify()文档解释了

应该只使用final对象作为监视器。这会帮你避免一些讨厌的虫子。

如果你的显示器不是最终的,总是有机会它将被设置为引用一个新对象,在这种情况下,看起来同步的代码实际上会运行并行执行。点击这里了解更多。

是这样做的:

。消费者:

static final Object monitor = new Object(); //<---------------
static volatile boolean completed = false;

public class ThreadA {
   public static void main(String[] args){
     ThreadB b = new ThreadB();
     b.start();
     synchronized(monitor) {
          while (!completed) { 
               monitor.wait();
          }
     }
     // when here: producer had completed <-----------------
  }
}

B。制作人:

class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        for(int i=0; i<100 ; i++) { //<------------ no need to synchronize 
             total += i;
        }
        completed = true; <--------- mark producer as completed
        synchronized(monitor) {
            monitor.notify(); 
        }
    }
}

不妨使用信号量,或者在本例中使用CountDownLatch。看一下Semaphore的源代码,wait和notify仅仅触及了表面。

使用CountDownLatch使代码更容易阅读:

import java.util.concurrent.CountDownLatch;
public class WaitOnCount {
public static void main(String[] args) {
    CountDownLatch latch = new CountDownLatch(1);
    ThreadB b = new ThreadB(latch);
    b.start();
    try {
        latch.await();
        System.out.println("Total is: " + b.total);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
static class ThreadB extends Thread {
    final CountDownLatch latch;
    int total;
    ThreadB(CountDownLatch latch) {
        super();
        this.latch = latch;
    }
    @Override
    public void run() {
        for(int i = 0; i < 100; i++) {
            total += i;
        }
        latch.countDown();
    }
}
}

最新更新