返回

Java 并发编程之 ReentrantReadWriteLock(五)写锁获取和释放

后端

前言

前面几篇文章介绍了读锁的加锁和解锁流程,内容较多比较复杂,写锁的流程相对就简单一些了,根据源码来看一下具体流程。

加锁

前面两步和 ReentrantLock 一样,通过 lock 方法进行加锁,然后调用 acquireWrite 方法,acquireWrite 方法的流程如下:

  1. 首先检查是否有线程持有写锁,如果有,则直接返回,让当前线程进入等待队列;
  2. 如果没有线程持有写锁,则检查是否有线程正在等待写锁,如果有,则让当前线程进入等待队列;
  3. 如果既没有线程持有写锁,也没有线程正在等待写锁,则直接获取写锁。

释放锁

释放写锁的流程很简单,只需要调用 unlockWrite 方法即可,unlockWrite 方法的流程如下:

  1. 首先检查是否有其他线程正在等待写锁,如果有,则唤醒这些线程;
  2. 然后释放写锁。

示例代码

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReentrantReadWriteLockDemo5 {

    private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public static void main(String[] args) {
        // 创建一个写线程
        Thread writeThread = new Thread(() -> {
            // 获取写锁
            lock.writeLock().lock();
            try {
                // 模拟写操作
                System.out.println(Thread.currentThread().getName() + " is writing...");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // 释放写锁
                lock.writeLock().unlock();
            }
        });

        // 创建一个读线程
        Thread readThread = new Thread(() -> {
            // 获取读锁
            lock.readLock().lock();
            try {
                // 模拟读操作
                System.out.println(Thread.currentThread().getName() + " is reading...");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // 释放读锁
                lock.readLock().unlock();
            }
        });

        // 启动写线程和读线程
        writeThread.start();
        readThread.start();
    }
}

运行结果

Thread-0 is writing...
Thread-1 is reading...

从运行结果可以看出,写线程先获取到了写锁,然后读线程才获取到了读锁,这说明写锁是排斥读锁的。