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 那些排它锁只允许在同一时刻只允许一个线程进行访问,读写锁可以允许多个 ...
随机推荐
- 算法<初级> - 第二章 队列、栈、哈希表相关问题
算法 - 第二章 数据结构 题目一 用数组实现大小固定的队列和栈(一面题) 数组实现大小固定栈 /*** * size是对头索引(initSize是固定大小) 也是当前栈大小 * size=下个进队i ...
- 在.Net Core 3.0中尝试新的System.Text.Json API
.NET Core 3.0提供了一个名为System.Text.Json的全新命名空间,它支持reader/writer,文档对象模型(DOM)和序列化程序.在此博客文章中,我将介绍它如何工作以及如何 ...
- javascript运行时中的堆栈和队列
下面是一个理论上的模型,js引擎着重实现和优化了描述的这几个语义 可视化描述 栈(stack) var a = 10; function bar(x) { var b = 5; fn(x + b); ...
- PHPStorm 10 配置PHPUnit
PHPStorm 10 配置PHPUnit PHPUnit的安装 自己用的是Xampp,PHPUnit好像自带不好用. 不说废话: 自己看 According to official site htt ...
- NetworkManager网络通讯_networkReader/Writer(六)
unet客户端和服务端进行消息发送时可以采用上一节中方法,也可以直接用networkReader/Writer类进行发送 (一)服务端/客户端注册消息 ; m_Server.RegisterHandl ...
- js中用面向对象的思想——淡入淡出轮播图
首先看下效果图 明确功能 1.前后切换(边界判断) 2.按键切换 3.自动轮播 css代码 <style> * {margin:0; padding:0;} li{list-style: ...
- 10、pytest -- skip和xfail标记
目录 1. 跳过测试用例的执行 1.1. @pytest.mark.skip装饰器 1.2. pytest.skip方法 1.3. @pytest.mark.skipif装饰器 1.4. pytest ...
- 关于Map集合注意事项
今日代码中循环Map时,采用循环主键 Map<Integer,Map<Integer,String>> status = new HashMap<>(); Set ...
- Bash 通配符、正则表达式、扩展正则表达式
BASH中的通配符(wildcard) *:任意长度的任意字符. ?:任意单个字符 []:匹配范围 [^]:排除匹配范围 [:alnum:]:所有字母和数字 [:alpha:]:所有字母 [:digi ...
- JavaSE(下)
11.抽象的(abstract)方法是否同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized? 都不能. 抽象方法需要子类重写,而静态的方法是无法被 ...