Java多线程(八):ReentrantReadWriteLock
读写锁ReentrantReadWriteLock概述
读写锁ReentrantReadWriteLock,使用它比ReentrantLock效率更高。
读写锁表示两个锁,一个是读操作相关的锁,称为共享锁;另一个是写操作相关的锁,称为排他锁。
1、读和读之间不互斥,因为读操作不会有线程安全问题
2、写和写之间互斥,避免一个写操作影响另外一个写操作,引发线程安全问题
3、读和写之间互斥,避免读操作的时候写操作修改了内容,引发线程安全问题
多个Thread可以同时进行读取操作,但是同一时刻只允许一个Thread进行写入操作。
读操作和读操作共享
请看例子
ThreadDomain44类和main方法
public class ThreadDomain44 extends ReentrantReadWriteLock
{
public void read()
{
try
{
readLock().lock();
System.out.println(Thread.currentThread().getName() + "获得了读锁, 时间为" +
System.currentTimeMillis());
Thread.sleep(10000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
readLock().unlock();
}
}
public static void main(String[] args)
{
final ThreadDomain44 td = new ThreadDomain44();
Runnable readRunnable = new Runnable()
{
public void run()
{
td.read();
}
};
Thread t0 = new Thread(readRunnable);
Thread t1 = new Thread(readRunnable);
t0.start();
t1.start();
}
}
输出结果如下
Thread-0获得了读锁, 时间为1564018325618
Thread-1获得了读锁, 时间为1564018325618
尽管加了Thread.sleep(10000);两个线程几乎同时执行lock()后面的方法。说明readLock().lock()允许多个线程执行并且能提高执行效率。
写操作和写操作互斥
请看例子
public class ThreadDomain45 extends ReentrantReadWriteLock {
public void write()
{
try
{
writeLock().lock();
System.out.println(Thread.currentThread().getName() + "获得了写锁, 时间为" +
new Date());
Thread.sleep(10000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
writeLock().unlock();
}
}
public static void main(String[] args)
{
final ThreadDomain45 td = new ThreadDomain45();
Runnable readRunnable = new Runnable()
{
public void run()
{
td.write();
}
};
Thread t0 = new Thread(readRunnable);
Thread t1 = new Thread(readRunnable);
t0.start();
t1.start();
}
}
输出结果
Thread-1获得了写锁, 时间为Tue Jul 30 11:26:21 CST 2019
Thread-0获得了写锁, 时间为Tue Jul 30 11:26:31 CST 2019
可以看到,后获得锁的Thread-0等待了十秒,说明写和写互斥
读操作和写操作互斥/写操作和读操作互斥
例子如下
public class ThreadDomain46 extends ReentrantReadWriteLock {
public void write()
{
try
{
writeLock().lock();
System.out.println(Thread.currentThread().getName() + "获得了写锁, 时间为" +
new Date());
Thread.sleep(10000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
writeLock().unlock();
}
}
public void read()
{
try
{
readLock().lock();
System.out.println(Thread.currentThread().getName() + "获得了读锁, 时间为" +
new Date());
Thread.sleep(10000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
readLock().unlock();
}
}
public static void main(String[] args)
{
final ThreadDomain46 td = new ThreadDomain46();
Runnable readRunnable = new Runnable()
{
public void run()
{
td.read();
}
};
Runnable writeRunnable = new Runnable()
{
public void run()
{
td.write();
}
};
Thread t0 = new Thread(readRunnable);
Thread t1 = new Thread(writeRunnable);
t0.start();
t1.start();
}
}
输出结果如下
Thread-0获得了读锁, 时间为Tue Jul 30 11:49:15 CST 2019
Thread-1获得了写锁, 时间为Tue Jul 30 11:49:26 CST 2019
可以看到Thread-0获得读锁执行完10s后Thread-1才获得了写锁,说明读操作和写操作互斥。
另一种输出结果如下
Thread-1获得了写锁, 时间为Tue Jul 30 14:14:07 CST 2019
Thread-0获得了读锁, 时间为Tue Jul 30 14:14:17 CST 2019
可以看到Thread-1获得写锁执行完10s后Thread-0才获得了读锁,说明写操作和读操作互斥。
Java多线程(八):ReentrantReadWriteLock的更多相关文章
- Java多线程——<八>多线程其他概念
一.概述 到第八节,就把多线程基本的概念都说完了.把前面的所有文章加连接在此: Java多线程——<一>概述.定义任务 Java多线程——<二>将任务交给线程,线程声明及启动 ...
- java多线程(八)-死锁问题和java多线程总结
为了防止对共享受限资源的争夺,我们可以通过synchronized等方式来加锁,这个时候该线程就处于阻塞状态,设想这样一种情况,线程A等着线程B完成后才能执行,而线程B又等着线程C,而线程C又等着线程 ...
- java多线程:ReentrantReadWriteLock读写锁使用
Lock比传统的线程模型synchronized更多的面向对象的方式.锁和生活似,应该是一个对象.两个线程运行的代码片段要实现同步相互排斥的效果.它们必须用同一个Lock对象. 读写锁:分为读锁和写锁 ...
- 【Java多线程】ReentrantReadWriteLock
概述 ReentrantReadWriteLock是Lock的另一种实现方式,ReentrantLock是一个排他锁,同一时间只允许一个线程访问,而ReentrantReadWriteLock允许多个 ...
- Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock
概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...
- Java多线程(五) Lock接口,ReentranctLock,ReentrantReadWriteLock
在JDK5里面,提供了一个Lock接口.该接口通过底层框架的形式为设计更面向对象.可更加细粒度控制线程代码.更灵活控制线程通信提供了基础.实现Lock接口且使用得比较多的是可重入锁(Reentrant ...
- java多线程系列(八)---CountDownLatch和CyclicBarrie
CountDownLatch 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 java多线 ...
- Java多线程——线程八锁案例分析
Java多线程——线程八锁案例分析 摘要:本文主要学习了多线程并发中的一些案例. 部分内容来自以下博客: https://blog.csdn.net/dyt443733328/article/deta ...
- Java 多线程基础(八)线程让步
Java 多线程基础(八)线程让步 yield 一.yield 介绍 yield()的作用是让步.它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权:但是,并 ...
- java多线程7:ReentrantReadWriteLock
真实的多线程业务开发中,最常用到的逻辑就是数据的读写,ReentrantLock虽然具有完全互斥排他的效果(即同一时间只有一个线程正在执行lock后面的任务), 这样做虽然保证了实例变量的线程安全性, ...
随机推荐
- certbot 配置https屏蔽询问选项
平常直接在终端,刷https时,要sudo certbot --nginx这样执行,但是中间会出现选项,让选择. 写程序用脚本操作时,希望跳过这些选项,就用--agree-tos 参数,一步到位. s ...
- [Java] JRE、JDK和JVM的区别
在Java语言的学习过程中,配置环境时首先会接触到JRE和JDK的概念,后面随着了解的深入,不可避免会学习到JVM. JRE,全称Java Runtime Environment,也被写成Java R ...
- elasticsearch-6.4.3 集群搭建
1.准备三台服务器,已安装好es. 2.修改服务集群配置如下 使用命令: vi elasticsearch.yml 如下: cluster.name: myes ###保证三台服务器节点集群名称相同 ...
- Jquery.Data()和HTML标签的data-*属性
Jquery.Data()和HTML标签的data-*属性 一.总结 一句话总结: 在页面中用到要用标签存数据还是用HTML标签的data-*属性,这样 不会破坏html本身的结构 1.使用HTML标 ...
- git如何将一个远程仓库的某个分支拉取到当前分支?
答: git pull <remote_repository_url> <branch_name> 例如: git clone https://github.com/lede- ...
- PCA人脸识别学习笔记---原理篇
前言 在PCA人脸识别中我们把一个人脸图片看做一个特征向量,PCA做的事情就是:找到这样一组基向量来表示已有的数据点,不仅仅是将高维度数据变成低维度数据,更能够找到最关键信息. 假设已有数据{xi} ...
- fidder修改参数
进入截栏模式 inspectors,webfroms run
- Spring事务管理3----声明式事务管理(1)
声明式事务管理(1)基于 基于 tx/aop 这种事务管理相比编程式事务管理来说对业务层基本没有改动,通过 TransactionProxyFactoryBean 创建业务层的代理,通过A ...
- JavaScript 异步和单线程
JavaScript语言本身是单线程的,所以它自身不可能是异步.所谓单线程,就必然意味着:所有任务需要排队,前一个任务结束,才会执行后一个任务. 但js的宿主环境(比如浏览器,Node)是多线程的.宿 ...
- Spring Aop(五)——给Advice传参
转发:https://www.iteye.com/blog/elim-2395337 5 给Advice传递参数 Advice除了可以接收JoinPoint(非Around Advice)或Proce ...