Java中读写锁ReadWriteLock的使用案例和性能对比

ReadWriteLock介绍

ReadWriteLock 被称为读写锁,通过读读不加锁的方式区分业务,从而提高效率

读写锁与ReentLock锁的效率对比
我们用如下代码进行一个简单的对比

非公平模式(默认)
当以非公平初始化时,读锁和写锁的获取的顺序是不确定的。非公平锁主张竞争获取,可能会延缓一个或多个读或写线程,但是会比公平锁有更高的吞吐量。
公平模式
当以公平模式初始化时,线程将会以队列的顺序获取锁。当当前线程释放锁后,等待时间最长的写锁线程就会被分配写锁;或者有一组读线程组等待时间比写线程长,那么这组读线程组将会被分配读锁。

实例代码和性能对比

建议看着demo自己敲一下,可能会发现很多新的问题,记忆也更牢固

package ReentrantLockLongAdder;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @program: solution
 * @description: 演示ReadWriteLock的使用
 * @author: Wang Hai Xin
 * @create: 2022-11-14 10:10
 **/
public class ReadWritLockT {

    /**/
    static ReentrantLock lock = new ReentrantLock();

    static int value = 0;

    /*读写锁,ReentrantReadWriteLock 是读写锁ReadWriteLock的一种实现*/
    static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    /*可以通过 redLocke和writeLock分出两把锁使用*/
    static Lock read = readWriteLock.readLock();
    static Lock write = readWriteLock.writeLock();

    public static void main(String[] args) {

        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String format = simpleDateFormat.format(date);


        Runnable writeRunnable = () -> write(lock, 1);

//        Runnable writeRunnable = () -> write(write, 1);

        Runnable readRunnable = () -> read(lock);
//
//        Runnable readRunnable = () -> read(read);

        ArrayList<Thread> threads = new ArrayList<>();
        for (int i = 0; i < 18; i++) {
            threads.add(
                    new Thread(readRunnable)
            );

        }

        for (int i = 0; i < 2; i++) {
            threads.add(
                    new Thread(writeRunnable)
            );
        }

        for (int i = 0; i < threads.size(); i++) {
            threads.get(i).start();
        }

        for (int i = 0; i < threads.size(); i++) {
            try {
                threads.get(i).join();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }


        System.out.println("ReentrantLock开始时间"+format);



        Date date1 = new Date();
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String format1 = simpleDateFormat1.format(date1);
        System.out.println("ReentLock 结束时间:" + format1);

    }

    public static void read(Lock lock) {

        try {
            lock.lock();
            Thread.sleep(1000);
            System.out.println("读数据结束");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }

    }

    public static void write(Lock lock, int i) {
        try {
            lock.lock();
            Thread.sleep(1000);
            value += i;
            System.out.println("写操作完成");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }

}


ReentrantLock运行结果

读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
写操作完成
写操作完成
ReentrantLock开始时间2022-11-14 10:46:20 217
ReentLock 结束时间:2022-11-14 10:46:40 476

使用ReentrantReadWriteLock运行的结果为

// Runnable writeRunnable = () -> write(lock, 1);
//
Runnable writeRunnable = () -> write(write, 1);
//
// Runnable readRunnable = () -> read(lock);
Runnable readRunnable = () -> read(read);

读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
读数据结束
写操作完成
写操作完成
ReentrantLock开始时间2022-11-14 10:48:45 604
ReentLock 结束时间:2022-11-14 10:48:48 701

可以看出 在特定条件下,ReentrantReadWritLock的效率要比Reentrantlock的效率高很多。

使用场景以及注意事项

使用场景应该很好想了,就是读多写少的场景可以使用.

笔者不太推荐使用,
因为维护起来会很麻烦,如果业务逻辑复杂,后来的人很有可能就在读的逻辑中操作了数据。

锁降级

要实现一个读写锁,需要考虑很多细节,其中之一就是锁升级和锁降级的问题。什么是升级和降级呢?

在不允许中间写入的情况下,写入锁可以降级为读锁吗?读锁是否可以升级为写锁,优先于其他等待的读取或写入操作?简言之就是说,锁降级:从写锁变成读锁;锁升级:从读锁变成写锁,ReadWriteLock是否支持呢?

ReadWriteLock 不支持锁升级

ReadWriteLock 支持锁降级,但是!! 并不会自动释放写锁,需要显式的释放写锁,否则其它线程永远获取不到写锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑白极客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值