浅谈 JDK 的读写锁——ReentrantReadWriteLock

本文介绍了JDK1.5开始引入的ReentrantReadWriteLock,作为增强版的synchronized,提供了读写锁机制,提高了代码执行效率。在没有写操作时,多个线程可同时读取;有写操作时,读写互斥。通过四个实例展示了读锁与读锁、读锁与写锁、写锁与读锁、写锁与写锁之间的互斥关系。
摘要由CSDN通过智能技术生成

从 JDK1.5 开始,JDK 加入了 ReentrantLock 类,该类能够像 synchronized 关键字一样实现线程之间的同步互斥,并且在功能上比 synchronized 更强大,使用起来也更灵活。

然而,ReentrantLock 在某些情况下也有自身的不足,因为同一时间内只有一个线程能够获取到锁并执行,这虽然保证了线程的安全,但假设我们有多个线程只是需要对对象进行读取操作,并没有写操作,这个时候怎么办?用 ReentrantLock 上锁让线程们排队一个个读取吗?这样子效率就太低了,很扯,读取应该是大家都能一起读取。那直接不上锁怎么样呢?这确实可以让多个线程同时读取,但这也不实际,假设在众多的线程里面,有那么几个是要进行写操作的,这可怎么办?

我们上面假设的业务场景中,需要让线程可以同时进行读取,但是在写的过程中其他线程无法进行读取,于是,JKD 提供了读写锁——ReentrantReadWriteLock,在上面的场景中,我们可以使用 ReentrantReadWriteLock 提高代码的执行效率、同时也兼顾线程安全问题。

读写锁——ReentrantReadWriteLock

顾名思义,读写锁包含了两种类型的锁,一个是读锁(ReadLock),与读操作相关,也称作共享锁;另外一个是写锁(WriteLock),与写操作相关,也叫排他锁。

ReadLock 与 WriteLock 的关系如下:

  • ReadLock 与 ReadLock 不互斥
  • ReadLock 与 WriteLock 互斥
  • WriteLock 与 WriteLock 互斥

也即是,当没有线程获取到写锁的时候,同一时刻可以有多个线程可以获取到读锁并进行读操作;

当有线程获取到读锁的时候,其他线程只能获取读锁,没法获取写锁,需要等所有读锁都释放了,其他线程才能获取到写锁并进行写操作;

当有线程获取到写锁的时候,其他线程既不能获取读锁,也不能获取写锁,需要等写锁被释放了,其他线程才能获取读锁或者写锁;

实例演示

示例一:读锁与读锁之间不互斥

编写一个模拟读写的业务类 ReadWriteService,ReadWriteService 模拟了读操作和写操作,在读写完毕后释放对应的锁;

package com.shawearn.test.service;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写业务类;
 * <p>
 * author: shawearn
 * date: 2018-04-11 00:25
 */
public class ReadWriteService {
    
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    // 模拟读写操作所需消耗的时间,单位:毫秒;
    private final long sleepTime = 10000l;

    /**
     * 获取读锁;
     */
    public void read() {
    
        try {
    
            lock.readLock().lock();
            System.out.println(Thread.currentThread().getName()
                    + " 获取读锁 " + System.currentTimeMillis());

            // 线程阻塞 10000 毫秒,用以证明锁之间是否互斥;
            Thread.sleep(sleepTime);

            // 释放读锁;
            System.out.println(Thread.currentThread().getName()
                    + " 读完成,释放读锁 " + System.currentTimeMillis());
            lock.readLock().unlock();
        } catch (InterruptedException e) {
    
            e.printStackTrace();
        }
    }

    /**
     * 获取写锁;
     */
    public void write() {
    
        try {
    
            lock.writeLock().lock(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值