JAVA多线程系列--Lock锁-ReentrantLock之Condition应用

1.Condition

synchronized与wait()和nitofy()/notifyAll()方法相结合可以实现等待/通知模型,ReentrantLock同样可以,但是需要借助Condition,且Condition有更好的灵活性,具体体现在:
1、一个Lock里面可以创建多个Condition实例,实现多路通知
2、notify()方法进行通知时,被通知的线程时Java虚拟机随机选择的,但是ReentrantLock结合Condition可以实现有选择性地通知,这是非常重要的

3、在使用实现等待/通知模型的时候,await()和signal()之前,必须要先lock()获得锁,使用完毕在finally中unlock()释放锁,这和wait()/notify()/notifyAll()使用前必须先获得对象锁是一样的:


2. 例一:

/**
 * ReentrantLock
 * @author niyuelin
 *
 */
public class ReeterLockCondition implements Runnable{
   public static ReentrantLock lock = new ReentrantLock();
   public static Condition condition = lock.newCondition();
   @Override
   public void run() {
      lock.lock();
      try{
         //等待signal 释放,
         condition.await();
         System.out.println("Thread is going on");
      }catch(InterruptedException e){
         e.printStackTrace();
      }finally {
         lock.unlock();
      }
   }
   
   public static void main(String[] args) throws InterruptedException {
      ReeterLockCondition r1 = new ReeterLockCondition();
      Thread t1 = new Thread(r1);
      t1.start();
      Thread.sleep(2000);
      lock.lock();
      //释放condition
      condition.signal();
      lock.unlock();
      System.out.println(Runtime.getRuntime().availableProcessors());
   }
}

输出结果:

Thread is going on
4
await方法必须等待signal释放才能执行下面的代码。


3.例2:

一个简单的堵塞队列

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BoundedBuffer {
    final Lock lock = new ReentrantLock();
    final Condition notFull = lock.newCondition();
    final Condition notEmpty = lock.newCondition();

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

    //往队列里面存放元素
    public void put(Object x) throws InterruptedException {
        System.out.println("put wait lock");
        lock.lock();
        System.out.println("put get lock");
        try {
            while (count == items.length) {
                System.out.println("buffer full, please wait");
                notFull.await();
            }

            items[putptr] = x;
            if (++putptr == items.length)
                putptr = 0;
            ++count;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    //往队列里面获取元素
    public Object take() throws InterruptedException {
        System.out.println("take wait lock");
        lock.lock();
        System.out.println("take get lock");
        try {
            while (count == 0) {
                System.out.println("no elements, please wait");
                notEmpty.await();
            }
            Object x = items[takeptr];
            if (++takeptr == items.length)
                takeptr = 0;
            --count;
            notFull.signal();
            return x;
        } finally {
            lock.unlock();
        }
    }

}

1).队列存满,等待:

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

    Thread t1 = new Thread(new Runnable() {
        public void run() {
            for (int i = 0; i < 4; i++) {
                try {
                    bBuffer.put(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    });

    Thread t2 = new Thread(new Runnable() {
        public void run() {
            for (int i = 0; i < 1; i++) {
                try {
                    bBuffer.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    });
    t1.start();
    t2.start();
}


输出:

put wait lock
take wait lock
put get lock
put wait lock
take get lock
put get lock
put wait lock
put get lock
put wait lock
put get lock
buffer full, please wait

队列处于存储满的状态,故结果处于等待消费的状态。


2).队列原始未存储慢,等待消费:

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

    Thread t1 = new Thread(new Runnable() {
        public void run() {
            for (int i = 0; i < 1; i++) {
                try {
                    bBuffer.put(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    });

    Thread t2 = new Thread(new Runnable() {
        public void run() {
            for (int i = 0; i < 5; i++) {
                try {
                    bBuffer.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    });
    t1.start();
    t2.start();
}

输出结果:

put wait lock
take wait lock
take get lock
no elements, please wait
put get lock
take wait lock
take get lock
no elements, please wait


4.总结:

Condition  在队列和线程相关应用中,颇为广泛。

java自带堵塞队列大多数是基于Condition实现:ArrayBlockingQueue,DelayQueue,LinkedBlockingQueue。

当然Condition在高并发程序中也是必选的工具。

public class ArrayBlockingQueue<E> extends AbstractQueue<E>
        implements BlockingQueue<E>, java.io.Serializable {
/** Main lock guarding all access */ final ReentrantLock lock ; /** Condition for waiting takes */ private final Condition notEmpty ; /** Condition for waiting puts */ private final Condition notFull ;



发布了72 篇原创文章 · 获赞 52 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/niyuelin1990/article/details/78607030