Java中读写锁ReadWriteLock的使用案例和性能对比
创始人
2024-01-25 22:04:41
0

ReadWriteLock

  • ReadWriteLock介绍
  • 实例代码和性能对比
  • 使用场景以及注意事项
    • 锁降级

ReadWriteLock介绍

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

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

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

实例代码和性能对比

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

package ReentrantLock和LongAdder;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 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 支持锁降级,但是!! 并不会自动释放写锁,需要显式的释放写锁,否则其它线程永远获取不到写锁

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...