在重入锁等待条件(Waiting on a condition in a reentrant loc

2019-07-31 21:50发布

下面的代码是从拍摄的JavaDoc的Condition

class BoundedBuffer {
  final Lock lock = new ReentrantLock();
  final Condition notFull  = lock.newCondition(); 
  final Condition notEmpty = lock.newCondition(); 

  final Object[] items = new Object[100];
  int putptr, takeptr, count;

  public void put(Object x) throws InterruptedException {
    lock.lock();
    try {
      while (count == items.length) 
        notFull.await();
      items[putptr] = x; 
      if (++putptr == items.length) putptr = 0;
      ++count;
      notEmpty.signal();
    } finally {
      lock.unlock();
    }
  }

  public Object take() throws InterruptedException {
    lock.lock();
    try {
      while (count == 0) 
        notEmpty.await();
      Object x = items[takeptr]; 
      if (++takeptr == items.length) takeptr = 0;
      --count;
      notFull.signal();
      return x;
    } finally {
      lock.unlock();
    }
  } 
}

想象一下,2个线程, 消费者生产者 ,使用一个take ,一个put上的单个实例BoundedBuffer

比方说, 消费者先行,运行take()中,他锁定了lock ,现在环上notEmpty.await();

现在如何才能生产者可能进入put()方法经过锁紧的lock ,这是已经被消费者持有?

我缺少的是在这里吗? 在lock “临时解除”,而线程正在等待它的条件之一? 又是什么锁的重入的意思是,到底是什么?

Answer 1:

这两种Locksynchronized允许一个线程等待时放弃锁定,而另一个线程可以获取锁。 停止等待,一个线程必须重新获取锁。

注意:他们没有完全释放它,如果你需要一个堆栈跟踪,你可以有这似乎举行一次锁定多个线程,但在大多数人会运行(其余部分将被阻塞)

从Condition.await()

与此条件相关的锁以原子方式释放,并且当前线程的线程调度目的就退出,一直处于休眠状态的四两件事发生对象:

  • 一些其它线程调用信号()方法为这个条件和当前的线程正好被选择作为被唤醒线程; 要么
  • 一些其它线程调用此条件下的signalAll()方法; 要么
  • 其他某个线程中断当前线程,并且支持中断线程的挂起; 要么
  • “虚假唤醒”的发生。

在所有情况下,这种方法才能返回当前线程必须重新获取与此条件有关的锁。 当线程返回时,可以保证它保持此锁



Answer 2:

至于重入,这意味着持有一定的锁的线程可以再次重新获得相同的锁。 如果情况并非如此,一个synchronized方法就不能调用另一个synchronized同一个对象的方法。

重入不涉及您的问题的理解。



Answer 3:

我测试下面的代码与单个监视器和下面始终执行更好 - 测试2芯机上,成色性能低于10-15%的平均

 final Object sync = new Object();
  AtomicInteger add=new AtomicInteger();
  AtomicInteger remove=new AtomicInteger();
   final Object[] items = new Object[1];
   int putptr, takeptr, count;        

 public void add(Object x) throws InterruptedException {
       add.incrementAndGet();

     synchronized (sync) {

       while (count == items.length)
         sync.wait();
       items[putptr] = x;
       if (++putptr == items.length) putptr = 0;
       ++count;
       sync.notify();
        }
   }

   public Object remove() throws InterruptedException {
       remove.incrementAndGet();

     synchronized (sync) {

       while (count == 0)
         sync.wait();
       Object x = items[takeptr];
       if (++takeptr == items.length) takeptr = 0;
       --count;
       sync.notify();
       return x;

       }
   }


  public static void main(String[] args) {
    final BoundedBuffer bf=new BoundedBuffer();

    Thread put =new Thread(){
        public void run(){
        try {
            while(true)
            bf.add(new Object());
        } catch (InterruptedException e) {

        }
        }

    };
    put.start();

    Thread take= new Thread(){
        public void run(){
        try {
        while(true)
            bf.remove();
        } catch (InterruptedException e) {

        }
        }

    };
    take.start();

    try {
        Thread.sleep(1000L);
        put.interrupt();
        take.interrupt();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


    System.out.println("add:"+bf.add);
    System.out.println("remove:"+bf.remove);


文章来源: Waiting on a condition in a reentrant lock