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. sql查询入门

    SQL语言是一门相对来说简单易学却又功能强大的语言,它能让你快速上手并很快就能写出比较复杂的查询语句.但是对于大多数开发者来说,使用SQL语句查询数据库的时候,如果没有一个抽象的过程和一个合理的步骤, ...

  2. 用Python校准本地时间

    目录 1. 概念 1.1 基本概念 1.2 版本演进 2. 示例演示 2.1 前提条件 2.2 完整代码 2.3 其他问题 3. 参考信息: 1. 概念 1.1 基本概念 时间,对于我们来说很重要,什 ...

  3. 简单的Dos Unity操作(debug)

    使用adb命令启动Unity app,eg: adb shell am start -S -a android.intent.action.MAIN -n co.spe3d.sticker/com.u ...

  4. 关于./xhost: unable to open display问题的解决

    看了很多大同小异的帖子,都没能解决这个问题,以下是我的实测经验,注意第三步,很关键. 注:以下操作在确保vncserver.xdpyinfo服务正常的情况下进行 第一步:root登录,启动vncser ...

  5. zabbix清理监控历史mysql数据

    问题描述: 今天同事说有个zabbix监控数据库历史数据越来越多了, 让我帮忙清一下,顺便熟悉练练手,做个笔记 zabbix监控运行一段时间以后,会留下大量的历史监控数据 zabbix数据库一直在增大 ...

  6. Unity5-ABSystem(二):AssetBundle导出

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/lodypig/article/detai ...

  7. 调用微信js sdk

    场景:需要调用微信获取当前位置的借口. 途径:查看微信 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115 .后 ...

  8. android 9.0 Launcher3 去掉抽屉式,显示所有 app

    效果图 修改思路 1.增加全局控制变量 sys.launcher3.is_full_app,用来动态切换 2.增加两套布局,对应有抽屉和无抽屉 3.去除 allAppsButton 4.将 AllAp ...

  9. VS环境下基于C++的单链表实现

    ------------恢复内容开始------------ #include<iostream> using namespace::std; typedef int ElemType; ...

  10. 第六篇 视觉slam中的优化问题梳理及雅克比推导

    优化问题定义以及求解 通用定义 解决问题的开始一定是定义清楚问题.这里引用g2o的定义. \[ \begin{aligned} \mathbf{F}(\mathbf{x})&=\sum_{k\ ...