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

时间:2014-07-31 20:46:44

标签: java multithreading semaphore

我的代码如下:这是为了获取信号量的知识。代码是线程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()文档解释了这一点。

2 个答案:

答案 0 :(得分:6)

您应该只使用最终对象作为监视器。它会为你节省一些讨厌的错误。

如果您的显示器未成为最终显示器,则始终有可能将其设置为 引用一个新对象,在这种情况下,看似同步的代码实际上会运行 在平行下。请阅读here了解更多信息。

以下是它的完成方式:

:一种。消费者:

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(); 
        }
    }
}

答案 1 :(得分:0)

也可以使用Semaphore,或者在这种情况下使用CountDownLatch。查看source code for Semaphore,等待并通知表面。

使用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();
    }
}
}