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: 读写锁的更多相关文章

  1. 12. ReadWriteLock 读写锁

    package com.gf.demo11; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent. ...

  2. ReadWriteLock读写锁(八)

    前言:在JUC ReentrantReadWriteLock是基于AQS实现的读写锁实现. ReadWriteLock中定义了读写锁需要实现的接口,具体定义如下: public interface R ...

  3. java多线程 -- ReadWriteLock 读写锁

    写一条线程,读多条线程能够提升效率. 写写/读写 需要“互斥”;读读 不需要互斥. ReadWriteLock 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作.只要没有 writer,读取锁 ...

  4. GUC-9 ReadWriteLock : 读写锁

    import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWrit ...

  5. 22.ReadWriteLock读写锁

    import java.util.Random; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.R ...

  6. 【转】java并发编程系列之ReadWriteLock读写锁的使用

    前面我们讲解了Lock的使用,下面我们来讲解一下ReadWriteLock锁的使用,顾明思义,读写锁在读的时候,上读锁,在写的时候,上写锁,这样就很巧妙的解决synchronized的一个性能问题:读 ...

  7. Java多线程之ReadWriteLock读写锁简介与使用教程

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6558073.html  普通的锁在对某一内容加锁后,其他线程是不能访问的.但是我们要考虑这种情况:如果当前加锁 ...

  8. ReadWriteLock 读写锁(读书笔记)

     读写分离锁可以有效的帮助减少锁的竞争,提升系统的效率, 读-读不互斥 读读之间不阻塞 读-写互斥 读阻塞写,写也会阻塞读 写-写互斥 写写阻塞 在系统中,读操作次数远远大于写操作,则读写锁就可以发挥 ...

  9. Java并发:ReadWriteLock 读写锁

    读写锁在同一时刻可以允许多个线程访问,但是在写线程访问,所有的读线程和其他写线程均被阻塞. 读写锁不像 ReentrantLock 那些排它锁只允许在同一时刻只允许一个线程进行访问,读写锁可以允许多个 ...

随机推荐

  1. 你不知道的DIV+CSS的命名规则

    搜索引擎优化(seo)有很多工作要做,其中对代码的优化是一个很关键的步骤.为了更加符合SEO的规范,下面是目前比较好的CSS+DIV的命名规则 1DIV CLASS或者ID 页头:header 登录条 ...

  2. 百万年薪python之路 -- 软件的开发规范

    一. 软件的开发规范 什么是开发规范?为什么要有开发规范呢? 你现在包括之前写的一些程序,所谓的'项目',都是在一个py文件下完成的,代码量撑死也就几百行,你认为没问题,挺好.但是真正的后端开发的项目 ...

  3. 将windows项目移植到linux上

    提要:由于项目使用java开发,移植中没有什么编译问题(移植很快,但小问题多) 1.移植过程中遇到的问题: (1).由于项目中使用了 1024以下的端口号,导致网络通信一直出错 原因:因为Linux要 ...

  4. 学 Python (Learn Python The Hard Way)

    学 Python (Learn Python The Hard Way) Contents: 译者前言 前言:笨办法更简单 习题 0: 准备工作 习题 1: 第一个程序 习题 2: 注释和井号 习题 ...

  5. Python中xml和dict格式转换

    在做接口自动化的时候,请求数据之前都是JSON格式的,Python有自带的包来解决.最近在做APP的接口,遇到XML格式的请求数据,费了很大劲来解决,解决方式是:接口文档拿到的是XML,在线转化为js ...

  6. 子树问题(DP)

    这题显然是DP 首先,\(dp[i][j]\)表示树深度小于等于i,树的大小为j的有根树的数量$ 可以循环枚举根节点编号次大的子树的大小k. \(dp[i][j]=\sum^{j-1}_{k=1}dp ...

  7. 学习笔记59_python字符串处理

    python中,字符串可以使用 '或"括起来 1. 要想写成  "hellow "aaaa"  ",在python中,可以"hellow ' ...

  8. Ubuntu18.04 安装在VMware 14中无法全屏问题解决

    现象:在安装完Ubuntu18.04后发现在虚拟机中不能全屏,安装Vmware Tools后还是无法解决,修改分辨率亦不成功. 原因:WAYLAND限制 解决方法:取消ubuntu中的显示设备WAYL ...

  9. [考试反思]0910csp-s模拟测试42:追求

    显而易见的暴力骗分. T1想到了bitset但是发现MLE后弃了,部分分都没拿. T2想到正解贪心打暴力过不了大样例弃了. T3牛逼题暴力. 考场没什么大失误,还可以. 不要轻易放弃每一个思路,可能再 ...

  10. 第一行python代码

    Hello Python 其实和大家一样为了以后多一条生存之路,本人也比较感兴趣python,因为它相比较JAVA来说,实现功能真的太方便了. 万事开头难,python不例外,本人在校过程学习了jav ...