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后面的任务), 这样做虽然保证了实例变量的线程安全性, ...
随机推荐
- 感知机和BP神经网络
一.感知机 1.感知机的概念 感知机是用于二分类的线性分类模型,其输入是实例的特征向量,输出是实例的类别,类别取+1和-1二个值,+1代表正类,-1代表负类.感知机对应于输入空间(特征空间)中将实例分 ...
- C++的精髓——代码复用、接口复用
C++的精髓——代码复用.接口复用 在另一篇文章中提到C++三大特点的核心概括,也写在这里吧.封装:信息隐藏继承:代码复用多态:面向对象C++并不是面向对象,它包容多种编程思想,如面向过程,面向对象, ...
- 十个Python爬虫武器库示例,十个爬虫框架,十种实现爬虫的方法!
一般比价小型的爬虫需求,我是直接使用requests库 + bs4就解决了,再麻烦点就使用selenium解决js的异步 加载问题.相对比较大型的需求才使用框架,主要是便于管理以及扩展等. 1.Scr ...
- php操作成功返回当前页并刷新
echo "<script>alert('操作成功');location.href='".$_SERVER["HTTP_REFERER"].&quo ...
- 怎么通过原生JS改变元素的class属性
解决方法:document.getElementById('test').className = 'emphasis' Eg: <!doctype html> <html lang= ...
- sersync+rsync做实时同步
(1).实验环境 源主机:youxi1 192.168.5.101 目的主机:youxi2 192.168.5.102 目的:实时同步数据 sersync默认端口874,rsync默认端口873 (2 ...
- Flutter 异步Future与FutureBuilder实用技巧
什么是Future? Future表示在接下来的某个时间的值或错误,借助Future我们可以在Flutter实现异步操作.它类似于ES6中的Promise,提供then和catchError的链式调用 ...
- ajax提交文件,django测试脚本环境书写,froms组件,钩子函数
1.在新版本中,添加app是直接在settings设置中,将INSTALLED_APPS里添加app名字, 但是他的完整写法是 'app01.apps.App01Config' 因为新版本做了优 ...
- Java学习笔记-内部类
内部类在Android中有着大量的运用 内部类 内部类提供了更好的封装:内部类可以直接访问外部类的私有数据:匿名内部类适合那些只需要使用一次的类.非静态内部类不能拥有静态成员.内部类比外部类可以多使用 ...
- 不同Json工具对空串和NULL的序列号处理:net.sf.json 和 fastjson
目录 1.测试代码 2.测试结果: 3.总结: 4.注:Maven中引入net.sf.json的方式 net.sf.json 和 fastjson 对于空串和NULL的处理: 1.测试代码 packa ...