天天看点

锁(五):读写锁

  • 读写锁特性
特性:写写互斥、读写互斥、读读共享
锁降级:写线程获取写入锁后可以获取读取锁,然后释放写入锁,这样就从写入锁变成了读取锁,从而实现锁降级的特性      
  • 案例1
public class ReentrantReadWriteLockDemo {

    private int i = 0;
    private int j = 0;

    // 获取锁
    private ReadWriteLock lock = new ReentrantReadWriteLock();
    Lock readLock = lock.readLock();
    Lock writeLock = lock.writeLock();

    // 使用读锁
    public void out(){
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+"i的值====》"+i + "j的值====》"+j);
        }finally {
            readLock.unlock();
        }
    }

    // 使用写锁
    public void inCreate() {
        writeLock.lock();
        try {
            i++;
            Thread.sleep(500L);
            j++;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            writeLock.unlock();
        }
    }

    // 测试
    public static void main(String[] args) {
        ReentrantReadWriteLockDemo reentrantReadWriteLockDemo = new ReentrantReadWriteLockDemo();
        // 测试1,3个线程,先写后读
        for (int i = 0; i < 3; i++) {
            new Thread(()->{
                reentrantReadWriteLockDemo.inCreate();
                reentrantReadWriteLockDemo.out();
            }).start();
        }
    }

}

# 控制台结果:
Thread-2i的值====》3j的值====》3
Thread-1i的值====》3j的值====》3
Thread-0i的值====》3j的值====》3      
  • debug调试
  • 锁(五):读写锁
  • 线程0拿到写锁,释放写锁
  • 锁(五):读写锁
  • 执行完毕
  • 锁(五):读写锁
  • 之后执行线程1和线程2
  • 案例2
public class ReentrantReadWriteLockDemo {

    private int i = 0;
    private int j = 0;

    // 获取锁
    private ReadWriteLock lock = new ReentrantReadWriteLock();
    Lock readLock = lock.readLock();
    Lock writeLock = lock.writeLock();

    // 使用读锁
    public void out(){
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+"i的值====》"+i + "j的值====》"+j);
        }finally {
            readLock.unlock();
        }
    }

    // 使用写锁
    public void inCreate() {
        writeLock.lock();
        try {
            i++;
            Thread.sleep(500L);
            j++;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            writeLock.unlock();
        }
    }

    // 测试
    public static void main(String[] args) {
        ReentrantReadWriteLockDemo reentrantReadWriteLockDemo = new ReentrantReadWriteLockDemo();
        // 测试2,2个线程,先读后写
        new Thread(()->{
            reentrantReadWriteLockDemo.out();
        },"读线程").start();
        new Thread(()->{
            reentrantReadWriteLockDemo.inCreate();
        },"写线程").start();
    }

}      
  • debug调试
  • 锁(五):读写锁
  • 如下:读线程获取到锁,但还没有释放
  • 锁(五):读写锁
  • 切换到写线程,下一步时报错如下,说明读写是互斥的
  • 锁(五):读写锁
  • 案例3
public class ReentrantReadWriteLockDemo {

    private int i = 0;
    private int j = 0;

    // 获取锁
    private ReadWriteLock lock = new ReentrantReadWriteLock();
    Lock readLock = lock.readLock();
    Lock writeLock = lock.writeLock();

    // 使用读锁
    public void out(){
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+"i的值====》"+i + "j的值====》"+j);
        }finally {
            readLock.unlock();
        }
    }

    // 使用写锁
    public void inCreate() {
        writeLock.lock();
        try {
            i++;
            Thread.sleep(500L);
            j++;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            writeLock.unlock();
        }
    }

    // 测试
    public static void main(String[] args) {
        ReentrantReadWriteLockDemo reentrantReadWriteLockDemo = new ReentrantReadWriteLockDemo();
        // 测试3,2个线程,读读操作
        new Thread(()->{
            reentrantReadWriteLockDemo.out();
        },"读线程1").start();
        new Thread(()->{
            reentrantReadWriteLockDemo.out();
        },"读线程2").start();
    }

}      
  • debug调试
  • 首先读线程1获取到锁,但还没有释放
  • 锁(五):读写锁
  • 切换到读线程2,下一步,可以获取到锁,说明读读是共享的