【问题标题】:Semaphore synchronized wait() and notify() [closed]信号量同步等待()和通知()[关闭]
【发布时间】:2014-07-31 20:46:44
【问题描述】:

我有以下代码:这是为了了解信号量。代码是线程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() 文档解释了这一点。

【问题讨论】:

  • 您阅读过wait()notify() 的文档吗?
  • 顺便说一下,在线程对象上同步和等待通常是个坏主意。当你可以打电话给notifyAll() 时,你也可以打电话给notify()notify() 有道理的情况很少,最好是安全的。
  • @JonSkeet 谢谢,同步是为了让信号量的线程所有者如文档所述。

标签: java multithreading semaphore


【解决方案1】:

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

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

这是如何完成的:

A.消费者:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-12
      • 2015-01-26
      • 1970-01-01
      • 2014-02-20
      • 2017-09-16
      • 1970-01-01
      相关资源
      最近更新 更多