美文网首页Android developing tips
ReentrantLock和Condition理解及应用

ReentrantLock和Condition理解及应用

作者: 蝉翅的空响 | 来源:发表于2018-10-30 16:55 被阅读1次

    Condition:

    Condition是一个多线程间协调通信的工具类,使得某个,或者某些线程一起等待某个条件(Condition),只有当该条件具备( signal 或者 signalAll方法被带调用)时 ,这些等待线程才会被唤醒,从而重新争夺锁。

    ReentrantLock:

    (重入锁)是jdk的concurrent包提供的一种独占锁的实现。它继承自Dong Lea的 AbstractQueuedSynchronizer(同步器),确切的说是ReentrantLock的一个内部类继承了AbstractQueuedSynchronizer,ReentrantLock只不过是代理了该类的一些方法,可能有人会问为什么要使用内部类在包装一层? 我想是安全的关系,因为AbstractQueuedSynchronizer中有很多方法,还实现了共享锁,Condition(稍候再细说)等功能,如果直接使ReentrantLock继承它,则很容易出现AbstractQueuedSynchronizer中的API被无用的情况。

    对比wati,notify,notifyAll

    java 1.5 出现的显式协作Condition接口的 await、signal、signalAll 也可以说是普通并发协作 wait、notify、notifyAll 的升级;普通并发协作 wait、notify、notifyAll 需要与synchronized配合使用,显式协作Condition 的 await、signal、signalAll 需要与显式锁Lock配合使用(Lock.newCondition()),调用await、signal、signalAll方法都必须在lock 保护之内。

    和wait一样,await在进入等待队列后会释放锁和cpu,当被其他线程唤醒或者超时或中断后都需要重新获取锁,获取锁后才会从await方法中退出,await同样和wait一样存在等待返回不代表条件成立的问题,所以也需要主动循环条件判断;await提供了比wait更加强大的机制,譬如提供了可中断或者不可中断的await机制等;特别注意Condition也有wait、notify、notifyAll方法,因为其也是Object,所以在使用显式协作机制时千万不要和synchronized 情况下的协作机制混合使用,避免出现诡异问题。

    用一个stackoverflow的一个实现BlockingQueue例子让大家印象深刻一点:
    用wait,notify,notifyAll实现:

    public class BlockingQueue<T> {
        private Queue<T> mQueue = new LinkedList<>();
        private int mCapacity;
    
        public BlockingQueue(int capacity) {
            this.mCapacity = capacity;
        }
    
        public synchronized void put(T element) throws InterruptedException{
            while (mQueue.size() == mCapacity){
                wait();
            }
            mQueue.add(element);
            notify();
        }
    
        public synchronized T take() throws InterruptedException{
            while (mQueue.isEmpty()){
                wait();
            }
            T item = mQueue.remove();
            notify();
            return item;
        }
    
    }
    

    用await,signal,signalAll实现:

    public class BlockingQueue<T> {
        private Queue<T> mQueue = new LinkedList<>();
        private int mCapacity;
        private Lock mLock = new ReentrantLock();
        private Condition mNotFull = mLock.newCondition();
        private Condition mNotEmpty = mLock.newCondition();
    
        public BlockingQueue(int capacity) {
            this.mCapacity = capacity;
        }
    
        public synchronized void put(T element) throws InterruptedException{
            mLock.lockInterruptibly();
            try {
                while (mQueue.size() == mCapacity){
                    mNotFull.await();
                }
                mQueue.add(element);
                mNotFull.signal();
            }finally {
                mLock.unlock();
            }
        }
    
        public synchronized T take() throws InterruptedException{
            mLock.lockInterruptibly();
            try {
                while (mQueue.size() == 0){
                    mNotEmpty.await();
                }
                T item = mQueue.remove();
                mNotEmpty.signal();
                return item;
            }finally {
                mLock.unlock();
            }
        }
    
    }
    

    怎么理解Condition

    并发一枝花之 BlockingQueue

    相关文章

      网友评论

        本文标题:ReentrantLock和Condition理解及应用

        本文链接:https://www.haomeiwen.com/subject/cnwgtqtx.html