美文网首页收藏
图解ReentrantReadWriteLock

图解ReentrantReadWriteLock

作者: 程序员札记 | 来源:发表于2022-04-03 17:42 被阅读0次

    我们先看一个典型的Dictionary 的一段代码 ,

    package com.concurreny.aqs;
    
    import java.util.Map;
    import java.util.TreeMap;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
    
    import javax.xml.crypto.Data;
    //读写锁ReentrantReadWriteLock:读读共享,读写互斥,写写互斥!
    public class ReentrantWriteReadLockTest {
        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
        ReadLock readLock = lock.readLock();
        WriteLock writeLock = lock.writeLock();
        
        public void read(){
            try {
                readLock.lock();
                System.out.println("线程"+Thread.currentThread().getName()+"进入。。。");
                Thread.sleep(3000);
                System.out.println("线程"+Thread.currentThread().getName()+"退出。。。");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                readLock.unlock();
            }
        }
        
        public void write(){
            try {
                writeLock.lock();
                System.out.println("线程"+Thread.currentThread().getName()+"进入。。。");
                Thread.sleep(3000);
                System.out.println("线程"+Thread.currentThread().getName()+"退出。。。");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally{
                writeLock.unlock();
            }
        }
        
     
        public static void main(String[] args) {
            final ReentrantWriteReadLockTest wr = new ReentrantWriteReadLockTest();
            Thread t1 = new Thread(new Runnable() {
                public void run() {
                    wr.read();
                }
            }, "t1");
            Thread t2 = new Thread(new Runnable() {
                public void run() {
                    wr.read();
                }
            }, "t2");
            Thread t3 = new Thread(new Runnable() {
                public void run() {
                    wr.write();
                }
            }, "t3");
            Thread t4 = new Thread(new Runnable() {
                public void run() {
                    wr.write();
                }
            }, "t4");
            
            t1.start();
            t2.start();
            //t3.start();
            //t4.start();
        }
    
    }
    class RWDictionary {
        private final Map<String, Data> m = new TreeMap<String, Data>();
        private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
        private final Lock r = rwl.readLock();
        private final Lock w = rwl.writeLock();
    
        public Data get(String key) {
            r.lock();
            try { return m.get(key); }
            finally { r.unlock(); }
        }
        public String[] allKeys() {
            r.lock();
            try { return (String[]) m.keySet().toArray(); }
            finally { r.unlock(); }
        }
        public Data put(String key, Data value) {
            w.lock();
            try { return m.put(key, value); }
            finally { w.unlock(); }
        }
        public void clear() {
            w.lock();
            try { m.clear(); }
            finally { w.unlock(); }
        }
     }
    
    • Read lock has no condition object
    • Does not support to upgrade lock
    r.lock()
        w.lock();
         try{
        } finally{
          w.unlock()
       }
    try{
    }finally{
       r.unlock()
    }
    
    
    • support to downgrade lock
    w.lock()
        r.lock();
         try{
        } finally{
          r.unlock()
       }
    try{
    }finally{
       w.unlock()
    }
    

    Case 分享

    • 下面看这个例子t1 写锁, t2 是读锁, t1获得了锁


    此时线程owner 是t1, state 0_1 值为1

    • 此时t2 前来尝试获得读锁


      image.png
    • t2 拿不到锁,进行排队
    image.png
    • 在来t3 是读锁,t4 是写锁, t3 ,t4 排队


      image.png
    • t1 释放写锁
    image.png

    此时t2 获得了锁,但是不是exclusive 的的, state 现在为0

    • 在t1 release 时候,unpark t2, ,t2 里从park状态激活,state =1_0
    image.png

    同时 t2 进入到doAcquireShared 线程 循环 运行setHeadAndPropagate,

       private void setHeadAndPropagate(Node node, int propagate) {
            Node h = head; // Record old head for check below
            setHead(node);
            if (propagate > 0 || h == null || h.waitStatus < 0 ||
                (h = head) == null || h.waitStatus < 0) {
                Node s = node.next;
                if (s == null || s.isShared())
                    doReleaseShared();
            }
        }
    
    

    再进入doReleaseShared, 在此时释放t2. t2 节点从队列去除。 t3 线程被unpark, t3 节点成为头结点。 当它进入doAcquireShared->setHeadAndPropagate 进入不了doReleaseShared, 因为t4 不是shared 的,所以t4 线程不能被激活。在此时state 为2_0

    image.png

    相关文章

      网友评论

        本文标题:图解ReentrantReadWriteLock

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