chapter14_构建自定义的同步工具_3_显式的Condition对象

博客介绍了Java中Condition接口,它是广义的条件队列,在java.util.concurrent.locks包中。可代替原生条件队列,一个Condition对象与Lock对象关联,Lock可关联多个Condition。使用时要用await、signal、signalAll方法,示例展示了使用Condition的优点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • (1) Condition是一种广义的条件队列

    (2) 在java.util.concurrent.locks包中, Condition是一个接口

      public interface Condition {
    
          void await() throws InterruptedException;
    
          void awaitUninterruptibly();
    
          long awaitNanos(long nanosTimeout) throws InterruptedException;
    
          boolean await(long time, TimeUnit unit) throws InterruptedException;
    
          boolean awaitUntil(Date deadline) throws InterruptedException;
    
          void signal();
    
          void signalAll();
      }
    

    (3) 如果想编写一个带有多个条件谓词的并发对象, 或者想获得更多对条件队列的控制权, 那么就可以考虑用Condition代替原生条件队列

    (4) 一个Condition对象和一个Lock对象关联在一起(就像一个条件队列和一个内置锁关联一样);

    但是一个Lock对象可以关联任意数量的Condition对象(通过Lock的Condition newCondition();方法)

    (5) Condition对象继承了相关的Lock对象的公平性(如果Lock是公平的, 那么线程会按照FIFO从Condition的await中释放)

    (6) wait、notify、notifyAll是Object的方法, 由于Object是所有类的基类, 所以Condition的实现类也有这三个方法. __但是, 使用Condition要用它的await、signal、signalAll方法

  • (1) 示例

      @ThreadSafe
      public class ConditionBoundedBuffer<T> {
    
          private static final int BUFFER_SIZE = 100;
    
          protected final Lock lock = new ReentrantLock();
    
          // CONDITION PREDICATE: notFull (count < items.length)
          private final Condition notFull = lock.newCondition();
    
          // CONDITION PREDICATE: notEmpty (count > 0)
          private final Condition notEmpty = lock.newCondition();
    
          @GuardedBy("lock")
          private final T[] items = (T[]) new Object[BUFFER_SIZE];
    
          @GuardedBy("lock")
          private int tail, head, count;
    
          // BLOCKS-UNTIL: notFull
          public void put(T x) throws InterruptedException {
    
              lock.lock();
    
              try {
                  while (count == items.length) {
                      notFull.await();
                  }
    
                  items[tail] = x;
    
                  if (++tail == items.length) {
                      tail = 0;
                  }
    
                  ++count;
                  notEmpty.signal();
    
              } finally {
    
                  lock.unlock();
              }
          }
    
          // BLOCKS-UNTIL: notEmpty
          public T take() throws InterruptedException {
    
              lock.lock();
    
              try {
                  while (count == 0) {
                      notEmpty.await();
                  }
    
                  T x = items[head];
                  items[head] = null;
    
                  if (++head == items.length) {
                      head = 0;
                  }
    
                  --count;
    
                  notFull.signal();
    
                  return x;
    
              } finally {
    
                  lock.unlock();
              }
          }
      }
    

    (2) 这个示例使用Condition, 优点有两个:

    1. 容易理解: put操作等待的是notFull条件, take操作等待的是notEmpty条件

    2. 使用signal而非signalAll, 效率高:

    之所以敢使用signal, 是因为当前的情境满足了那两个条件(见"2_使用条件队列.md"中的"什么时候可以放心大胆的使用notify"); 而用两个不同的Condition保证了其中一个条件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值