美文网首页收藏
图解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