ReadWriteLock: 读写锁
ReadWriteLock: 读写锁
ReadWriteLock:
JDK1.5提供的读写分离锁,采用读写锁分离可以有效帮助减少锁竞争。
特点:
1).使用读写锁。当线程只进行读操作时,可以允许多个线程同时读
2).写写操作,读写操作间依然需要相互等待和持有锁。
一).使用读写锁与使用重入锁进行读读写操作
开启200个线程,测试读写锁和重入锁的读效率。
使用重入锁进行读写操作:ReentrantLock_Rw
import java.util.concurrent.locks.ReentrantLock;
/**
* 使用重入锁进行读写操作
* 线程的读写使用同一把锁。
*/
public class ReentrantLock_RW {
private static ReentrantLock lock = new ReentrantLock();
private static int value ;
//读操作
public Object handleRead() throws InterruptedException {
try {
//获取锁
lock.lock();
//模拟读操作,读操作耗时越多,读写锁的优势越明显
Thread.sleep(1);
return value;
}finally {
lock.unlock();
}
}
/**
* 写操作
*/
public void handleWrite(int i) throws InterruptedException {
try {
lock.lock();
//模拟写操作
Thread.sleep(1);
value = i;
}finally {
lock.unlock();
}
}
}
使用ReadWriteLock进行读写操作: ReadWriteLock_RW
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 使用ReadWriteLock进行读写操作
*/
public class ReadWriteLock_RW {
private static int value;
private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
/**
* 读取锁
*/
private static Lock readLock = readWriteLock.readLock();
/**
* 写入锁
*/
private static Lock writeLock = readWriteLock.writeLock();
/**
* 读操作
*/
public Object handleRead() throws InterruptedException {
try {
readLock.lock();
Thread.sleep(1);
return value;
}finally {
//释放锁
readLock.unlock();
}
}
/**
* 写操作
*/
public void handleWrite(int index) throws InterruptedException {
try{
//获取锁
writeLock.lock();
Thread.sleep(1);
value = index;
}finally {
//释放锁
writeLock.unlock();
}
}
}
二)、测试多线程运行时间的知识储备
参考:https://www.cnblogs.com/jack-xsh/p/8615644.html
怎么测试多线程的运行时间?
//指定要开启的线程数
final static CountdownLatch countdownLatch = new CountdownLatch(200);
//每执行完一个线程,countdownLatch的线程数减一。
countdownLatch.countdown();
//挂起主线程,当cuntdown()的线程数为0,恢复主线程。
countdownLatch.await();
三)、使用重入锁进行读操作性能测试
重入锁读操作线程:ReentrantLockReadThread
**
* 比较重入锁与读写锁读数据的性能
*/
public class ReentrantLockReadThread implements Runnable{
//闭锁,线程计时工具
private CountDownLatch countDownLatch;
private ReentrantLock_RW reentrantLockRw;
public ReentrantLockReadThread(ReentrantLock_RW reentrantLockRw, CountDownLatch countDownLatch) {
this.reentrantLockRw = reentrantLockRw;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
reentrantLockRw.handleRead();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//线程执行完将线程挂起
countDownLatch.countDown();
}
}
}
重入锁读线程效率:ReentrantLockReadThreadTest
public class ReentrantLockReadThreadTest {
//程序计计时器,用于计算多线程的执行时间
final static CountDownLatch countDownLatch = new CountDownLatch(200);
//其实开启200个线程读取lock中值的速率
public static void main(String[] args) throws InterruptedException {
ReentrantLock_RW reentrantLockRw = new ReentrantLock_RW();
ReentrantLockReadThread readThread = new ReentrantLockReadThread(reentrantLockRw, countDownLatch);
long time = System.currentTimeMillis();
for(int i = 0; i < 200; i++){
Thread t = new Thread(readThread);
t.start();
}
//将主线程挂起
countDownLatch.await();
System.out.println(System.currentTimeMillis() - time);
}
}
结果:
2194
四)、使用读写锁进行读操作的性能测试
读写锁读操作线程:ReadLockThread
import java.util.concurrent.CountDownLatch;
/**
* 读入锁线程
*/
public class ReadLockThread implements Runnable{
private ReadWriteLock_RW readWriteLockrw;
private CountDownLatch countDownLatch;
public ReadLockThread(ReadWriteLock_RW readWriteLockrw, CountDownLatch countDownLatch) {
this.readWriteLockrw = readWriteLockrw;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
readWriteLockrw.handleRead();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//线程执行完将该线程挂起
countDownLatch.countDown();
}
}
}
读线程读写效率测试:ReadLockThreadTest
import java.util.concurrent.CountDownLatch;
/**
* 测试使用ReadLock的性能
*/
public class ReadLockThreadTest {
final static CountDownLatch countDownLatch = new CountDownLatch(200);
public static void main(String[] args) throws InterruptedException {
ReadWriteLock_RW readWriteLockRw = new ReadWriteLock_RW();
ReadLockThread readThread = new ReadLockThread(readWriteLockRw, countDownLatch);
long time = System.currentTimeMillis();
for(int i = 0; i < 200; i++){
Thread t = new Thread(readThread);
t.start();
}
countDownLatch.await(); //一定要等到countDown()方法执行完毕后才使用,将主线程挂起
System.out.println(System.currentTimeMillis() - time);
}
}
结果:
26
结论:使用读写锁来对数据进行读取,效率远远高于重入锁。
五)、使用重入锁进行写操作的性能比较
重入锁写操作线程:ReentrantLockWriteThread
public class ReentrantLockWriteThread implements Runnable {
private CountDownLatch countDownLatch;
private ReentrantLock_RW reentrantLockRw;
public ReentrantLockWriteThread(ReentrantLock_RW reentrantLockRw, CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
this.reentrantLockRw = reentrantLockRw;
}
@Override
public void run() {
try {
reentrantLockRw.handleWrite(1);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//线程执行完,线程数减一
countDownLatch.countDown();
}
}
}
写线程效率测试:ReentrantLockWriteThreadTest
public class ReentrantLockWriteThreadTest {
final static CountDownLatch countDownLatch = new CountDownLatch(200);
public static void main(String[] args) throws InterruptedException {
ReentrantLock_RW reentrantLockRw = new ReentrantLock_RW();
long start = System.currentTimeMillis();
for(int i = 0; i < 200; i++){
Thread t = new Thread(new ReentrantLockWriteThread(reentrantLockRw, countDownLatch));
t.start();
}
countDownLatch.await();
System.out.println(System.currentTimeMillis() - start);
}
}
结果:
408
六)、使用读写锁进行写操作性能比较
读写锁写操作线程: WriteLockThread
public class WriteLockThread implements Runnable{
private ReadWriteLock_RW readWriteLockrw;
private CountDownLatch countDownLatch;
public WriteLockThread(ReadWriteLock_RW readWriteLockrw, CountDownLatch countDownLatch) {
this.readWriteLockrw = readWriteLockrw;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
readWriteLockrw.handleWrite(1);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//线程执行完将该线程挂起
countDownLatch.countDown();
}
}
}
写线程效率测试:WriteLockThreadTest
public class WriteLockThread implements Runnable{
private ReadWriteLock_RW readWriteLockrw;
private CountDownLatch countDownLatch;
public WriteLockThread(ReadWriteLock_RW readWriteLockrw, CountDownLatch countDownLatch) {
this.readWriteLockrw = readWriteLockrw;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
readWriteLockrw.handleWrite(1);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//线程执行完将该线程挂起
countDownLatch.countDown();
}
}
}
结果:
398
结论:使用读写锁和重入锁进行写操作的速率大致相同。
在读多写少的场合,使用读写锁可以分离读操作和写操作,使所有读操作间
真正的并行。
使用场景:当线程使用读写操作共享数据时,使用读写锁,可以减少读线程的等待
时间提高系统的并发能力。
ReadWriteLock: 读写锁的更多相关文章
- 12. ReadWriteLock 读写锁
package com.gf.demo11; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent. ...
- ReadWriteLock读写锁(八)
前言:在JUC ReentrantReadWriteLock是基于AQS实现的读写锁实现. ReadWriteLock中定义了读写锁需要实现的接口,具体定义如下: public interface R ...
- java多线程 -- ReadWriteLock 读写锁
写一条线程,读多条线程能够提升效率. 写写/读写 需要“互斥”;读读 不需要互斥. ReadWriteLock 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作.只要没有 writer,读取锁 ...
- GUC-9 ReadWriteLock : 读写锁
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWrit ...
- 22.ReadWriteLock读写锁
import java.util.Random; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.R ...
- 【转】java并发编程系列之ReadWriteLock读写锁的使用
前面我们讲解了Lock的使用,下面我们来讲解一下ReadWriteLock锁的使用,顾明思义,读写锁在读的时候,上读锁,在写的时候,上写锁,这样就很巧妙的解决synchronized的一个性能问题:读 ...
- Java多线程之ReadWriteLock读写锁简介与使用教程
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6558073.html 普通的锁在对某一内容加锁后,其他线程是不能访问的.但是我们要考虑这种情况:如果当前加锁 ...
- ReadWriteLock 读写锁(读书笔记)
读写分离锁可以有效的帮助减少锁的竞争,提升系统的效率, 读-读不互斥 读读之间不阻塞 读-写互斥 读阻塞写,写也会阻塞读 写-写互斥 写写阻塞 在系统中,读操作次数远远大于写操作,则读写锁就可以发挥 ...
- Java并发:ReadWriteLock 读写锁
读写锁在同一时刻可以允许多个线程访问,但是在写线程访问,所有的读线程和其他写线程均被阻塞. 读写锁不像 ReentrantLock 那些排它锁只允许在同一时刻只允许一个线程进行访问,读写锁可以允许多个 ...
随机推荐
- 你不知道的DIV+CSS的命名规则
搜索引擎优化(seo)有很多工作要做,其中对代码的优化是一个很关键的步骤.为了更加符合SEO的规范,下面是目前比较好的CSS+DIV的命名规则 1DIV CLASS或者ID 页头:header 登录条 ...
- 百万年薪python之路 -- 软件的开发规范
一. 软件的开发规范 什么是开发规范?为什么要有开发规范呢? 你现在包括之前写的一些程序,所谓的'项目',都是在一个py文件下完成的,代码量撑死也就几百行,你认为没问题,挺好.但是真正的后端开发的项目 ...
- 将windows项目移植到linux上
提要:由于项目使用java开发,移植中没有什么编译问题(移植很快,但小问题多) 1.移植过程中遇到的问题: (1).由于项目中使用了 1024以下的端口号,导致网络通信一直出错 原因:因为Linux要 ...
- 学 Python (Learn Python The Hard Way)
学 Python (Learn Python The Hard Way) Contents: 译者前言 前言:笨办法更简单 习题 0: 准备工作 习题 1: 第一个程序 习题 2: 注释和井号 习题 ...
- Python中xml和dict格式转换
在做接口自动化的时候,请求数据之前都是JSON格式的,Python有自带的包来解决.最近在做APP的接口,遇到XML格式的请求数据,费了很大劲来解决,解决方式是:接口文档拿到的是XML,在线转化为js ...
- 子树问题(DP)
这题显然是DP 首先,\(dp[i][j]\)表示树深度小于等于i,树的大小为j的有根树的数量$ 可以循环枚举根节点编号次大的子树的大小k. \(dp[i][j]=\sum^{j-1}_{k=1}dp ...
- 学习笔记59_python字符串处理
python中,字符串可以使用 '或"括起来 1. 要想写成 "hellow "aaaa" ",在python中,可以"hellow ' ...
- Ubuntu18.04 安装在VMware 14中无法全屏问题解决
现象:在安装完Ubuntu18.04后发现在虚拟机中不能全屏,安装Vmware Tools后还是无法解决,修改分辨率亦不成功. 原因:WAYLAND限制 解决方法:取消ubuntu中的显示设备WAYL ...
- [考试反思]0910csp-s模拟测试42:追求
显而易见的暴力骗分. T1想到了bitset但是发现MLE后弃了,部分分都没拿. T2想到正解贪心打暴力过不了大样例弃了. T3牛逼题暴力. 考场没什么大失误,还可以. 不要轻易放弃每一个思路,可能再 ...
- 第一行python代码
Hello Python 其实和大家一样为了以后多一条生存之路,本人也比较感兴趣python,因为它相比较JAVA来说,实现功能真的太方便了. 万事开头难,python不例外,本人在校过程学习了jav ...