Java多线程之读写锁机制
Java多线程中有很多的锁机制,他们都有各自的应用场景,例如今天我说的这种锁机制:读写锁
读写锁,见名知意,主要可以进行两种操作,读和写操作,他们之间结合使用起来又是各不相同的。比如多个线程之间可以同时读,但不可以同时写,也不可以一边读一边写,有点类似于数据库中的共享锁以及排它锁,下面我具体事例演示:
需要注意的是,不管是进行读操作还是写操作,一定要成对去调用方法,就是开启锁后一定要关闭,且为了保险起见,关闭最好要写在finally语句块中去。
另外,我们在声明对象时,有两种方式(有参数和无参数),若为true则为公平机制,默认为false,不写也为false
简单举例演示
package day_12_27;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author soberw
* @Classname ReadWriteLockTest
* @Description ReadWriteLock的测试
* @Date 2021-12-27 10:10
*/
public class ReadWriteLockTest {
public static void main(String[] args) {
var rwl = new RWL();
//情况一:
new Thread(() -> rwl.write(100), "A").start();
//情况二:
// new Thread(() -> rwl.write(99), "AA").start();
// new Thread(() -> rwl.write(88), "AAA").start();
for (int i = 0; i < 20; i++) {
new Thread(rwl::read, "B" + i).start();
}
}
}
class RWL {
//可以传参,若为true则为公平锁,默认为false,不写也为false
private ReadWriteLock rwl = new ReentrantReadWriteLock();
public int number;
void write(int number) {
rwl.writeLock().lock();
try {
this.number = number;
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + ":start--" + number);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
rwl.writeLock().unlock();
}
}
void read() {
rwl.readLock().lock();
try {
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + ":" + number);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
rwl.readLock().unlock();
}
}
}
先分析代码,写线程两秒后写入一个线程“A”,然后开启20个读线程都去读数据,结果:

在写的时候,会停顿两秒,因为我加了sleep(),但是我在读的时候也加了阻塞,却发现20个进程还是同时执行了,这就说明多个进程之间可以同时读,且读写不能同时进行,当线程写的时候,其他所有的读线程都要等着
下面打开情况二,多个线程都进行写操作:

发现会一个一个执行,间隔两秒,并不会像读操作一样,同时进行,这说明写不能同时进行
应用场景举例
那么在实际开发中,常用这种锁机制来完成缓存系统的操作。所谓缓存系统,举个例子,就比如用户要读取某个数据的时候,我不直接去向数据库请求,而是先看我内部有没有这个数据,如果有就直接返回,如果没有,就从数据库中查找这个数,查到后将这个数据存入我内部存储器中,下次再有人来要这个数据,我就直接返回这个数不用再到数据库中找了,这就大大的避免了频繁的访问数据库。下面我就书写代码模拟这一过程:
package day_12_27;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author soberw
* @Classname ExerData
* @Description 模拟缓存系统
* @Date 2021-12-27 20:02
*/
public class ExerData {
private static ReadWriteLock rwLock = new ReentrantReadWriteLock();
private static Map<String, Object> map = new HashMap<String, Object>();
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
final String key = i + "";
new Thread(new Runnable() {
@Override
public void run() {
for (int i1 = 0; i1 < 5; i1++) {
System.out.println(Thread.currentThread().getName() + " read data: " + getData(key));
}
}
}).start();
}
}
public static Object getData(String key) {
rwLock.readLock().lock();
Object value = null;
try {
value = map.get(key);
if (value == null) {
rwLock.readLock().unlock();
rwLock.writeLock().lock();
try {
if (value == null) {
// 此处在实际应用中,就是从数据库中查找数据,放入缓存中
value = Thread.currentThread().getName() + new Date();
}
} finally {
rwLock.writeLock().unlock();
}
rwLock.readLock().lock();
}
} finally {
rwLock.readLock().unlock();
}
return value;
}
}
运行结果:

Java多线程之读写锁机制的更多相关文章
- java多线程 -- ReadWriteLock 读写锁
写一条线程,读多条线程能够提升效率. 写写/读写 需要“互斥”;读读 不需要互斥. ReadWriteLock 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作.只要没有 writer,读取锁 ...
- java 多线程 day12 读写锁
import java.util.Random;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent. ...
- 22、Java并发性和多线程-Java中的读/写锁
以下内容转自http://ifeve.com/read-write-locks/: 相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些.假设你的程序中涉及到对一些共享资源 ...
- 技术笔记:Delphi多线程应用读写锁
在多线程应用中锁是一个很简单又很复杂的技术,之所以要用到锁是因为在多进程/线程环境下,一段代码可能会被同时访问到,如果这段代码涉及到了共享资源(数据)就需要保证数据的正确性.也就是所谓的线程安全.之前 ...
- java中ReentrantReadWriteLock读写锁的使用
Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 读写锁:分为读 ...
- Java中的读写锁
一.读写锁 1.初识读写锁 a)Java中的锁——Lock和synchronized中介绍的ReentrantLock和synchronized基本上都是排它锁,意味着这些锁在同一时刻只允许一个线程进 ...
- Java多线程,对锁机制的进一步分析
1 可重入锁 可重入锁,也叫递归锁.它有两层含义,第一,当一个线程在外层函数得到可重入锁后,能直接递归地调用该函数,第二,同一线程在外层函数获得可重入锁后,内层函数可以直接获取该锁对应其它代码的控制权 ...
- JAVA线程锁-读写锁
JAVA线程锁,除Lock的传统锁,又有两种特殊锁,叫读写锁ReadWriteLock 其中多个读锁不互斥,读锁和写锁互斥,写锁和写锁互斥 例子: /** * java线程锁分为读写锁 ReadWri ...
- java并发编程-读写锁
最近项目中需要用到读写锁 读写锁适用于读操作多,写操作少的场景,假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁.在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以 ...
随机推荐
- linux 之 expect 交互操作(自动输入密码)
场景 需要实现执行一个命令,并自动输入密码. 实现 通过expect命令实现 spawn 交互程序开始后面跟命令或者指定程序expect 获取匹 ...
- 779. 第K个语法符号
<找规律> <递归> 题目描述 在第一行我们写上一个 0.接下来的每一行,将前一行中的0替换为01,1替换为10. 给定行数 N 和序数 K,返回第 N 行中第 K个字符.(K ...
- 深入理解Java虚拟机之自己编译JDK
题外话 最近在阅读<深入理解Java虚拟机>,其中有一小节实战是自己编译JDK,实际操作下来后遇到问题不少,为此特地记录,也希望可以给大家带来一些参考! 前置准备 平台及工具:Window ...
- Feed流系统重构-架构篇
重构,于我而言,很大的快乐在于能够解决问题. 第一次重构是重构一个c#版本的彩票算奖系统.当时的算奖系统在开奖后,算奖经常超时,导致用户经常投诉.接到重构的任务,既兴奋又紧张,花了两天时间,除了吃饭睡 ...
- Linux 安装 MySQL 8.0.26 超详细图文步骤
1.MySQL 8.0.26 下载 官方网站下载 MySQL 8.0.26 安装包,下载地址: https://downloads.mysql.com/archives/community/ 需要注意 ...
- 基于华为云服务器的FTP站点搭建
前言 主要介绍了华为云上如何使用弹性云服务器的Linux实例使用vsftpd软件搭建FTP站点.vsftpd全称是"very secure FTP daemon",是一款在Linu ...
- HttpRunner3的变量是如何传递的
HttpRunner3的变量可以在测试类的用例配置中通过variables添加,也可以在测试步骤中使用extract().with_jmespath()提取出来放到变量x,再用$x传递给下一个接口使用 ...
- vscode配置Microsoft C++注意事项
vscode配置c++插件教程链接如下: https://code.visualstudio.com/docs/cpp/config-msvc#_check-your-microsoft-visual ...
- MobaXterm中文乱码问题
现在Xshell和SecureCRT都要收费,本着不用盗版的原则,同时需要标签管理session,快捷命令等功能,最后选择了MobaXterm. 但是使用后发现中文会乱码.后按照博客的方法,修改了终端 ...
- rpc基础讲解
什么是RPC 本地过程调用 远程过程调用带来的3个问题 RPC的调用过程 RPC的具体过程如下 总结 RPC.HTTP.Restful之间的区别 通过httpserver实现rpc 首先一点需要明确: ...