美文网首页
JUC (07)ReentrantReadWriteLock

JUC (07)ReentrantReadWriteLock

作者: rock_fish | 来源:发表于2020-08-06 18:48 被阅读0次

    ReentrantReadWriteLock 可重入读写锁

    功能概述:

    并发处理过程中,避免不需要的锁等待,在数据不变的情况下,所有读取的线程不需要排队处理,可以同时进行。只有数据变更的操作跟其他操作是互斥的。

    方法介绍

    构造函数:指定公平还是非公平

    1. 读写两种锁,读操作使用读锁,写操作使用写锁。
    2. 每种锁都有其状态字段,等待队列和条件队列。
    ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    WriteLock writeLock = reentrantReadWriteLock.writeLock();
    
    writeLock.lock();
    try {
      ...
    }finally{
      writeLock.unlock();
    }
     ...
    ReadLock readLock = reentrantReadWriteLock.readLock() 
    readLock.lock();
    try{
      ...
    }finally{
      readLock.unlock();
    }
    

    排队规则

    公平锁:

    1. 队列空:
      1.1 R R 不排队(R:read,W :write)
      1.2 RW ,WW,WR 排队

    2. 队列不为空:
      2.1 RR 也排队
      2.2 RW,WW ,WR排队

    3. 当前线程W 升 R可以(不用排队),R升W不可以

    4. R被唤醒后,会唤醒后继的R,直到遇到W.在源码setHeadAndPropagate

    它会尝试去唤醒队列中下一个的处于Shared状态的节点。而下一个节点被唤醒时,会调用setHeadAndPropagate,来唤醒下一个Shared状态的节点。这样一直唤醒,直到遇见了一个独占状态的节点,这种连锁唤醒行动就停止了

    非公平锁:

    1. 队列空:
      1.1 R R 不排队
      1.2 RW ,WW,WR 排队

    2. 队列不为空:
      2.1 RR 不排队
      2.2 RW,WW,WR 排队

    3. 线程内W 升 R可以(不用排队),R升W不可以

    4. R被唤醒后,会唤醒后继的R,直到遇到W

    Demo

    import java.time.LocalDateTime;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    /**
     * https://blog.csdn.net/yanyan19880509/article/details/52435135
     * 公平:
     * 连续的读读不排队
     * 读写,写读 ,写写 排队
     */
    public class ReentrantReadWriteLockFairDemo {
        static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(true);
        static ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
        static ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();
        public static void main(String[] args) throws InterruptedException {
            readAndWrite();
        }
    
        public static  void readAndWrite() throws InterruptedException {
    
            Thread readThread1 = new Thread(ReentrantReadWriteLockFairDemo::read,"read1");
            Thread readThread2 = new Thread(ReentrantReadWriteLockFairDemo::read,"read2");
            Thread readThread3 = new Thread(ReentrantReadWriteLockFairDemo::read,"read3");
            Thread readThread4 = new Thread(ReentrantReadWriteLockFairDemo::read,"read4");
    
            Thread writeThread1 = new Thread(ReentrantReadWriteLockFairDemo::write,"write1");
            Thread writeThread2 = new Thread(ReentrantReadWriteLockFairDemo::write);
            Thread writeThread3 = new Thread(ReentrantReadWriteLockFairDemo::write);
    
            readThread1.start();
            readThread2.start();
    
            writeThread1.start();
    
            TimeUnit.SECONDS.sleep(1);
            readThread3.start();
            readThread4.start();
    
            writeThread2.start();
            writeThread3.start();
    
            readThread1.join();
            readThread2.join();
            readThread3.join();
            readThread4.join();
    
            writeThread1.join();
            writeThread2.join();
            writeThread3.join();
    
        }
    
        public static void read(){
            readLock.lock();
            try {
                try {
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(Thread.currentThread().getId() + " at: " + LocalDateTime.now() + " read");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //do something
            }finally {
                readLock.unlock();
            }
        }
    
        public static void write(){
            writeLock.lock();
            try {
                try {
                    TimeUnit.SECONDS.sleep(10);
                    System.out.println(Thread.currentThread().getId() + " at: " + LocalDateTime.now() + " write");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //do something
            }finally {
                writeLock.unlock();
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:JUC (07)ReentrantReadWriteLock

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