美文网首页
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