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. python学习-并发编程(十四)

    14.2线程的创建与启动 import threading # 定义一个普通的action函数,该函数准备作为线程执行体 def action(max): for i in range(max): p ...

  2. mongodb学习笔记系列一

    一.简介和安装 ./bin/mongod --dbpath /path/to/database --logpath /path/to/log --fork --port 27017 mongodb非常 ...

  3. Typora忘记保存的文件怎么找回

    打开Typora,选择文件--偏好设置,在通用设置下点击恢复未保存的草稿,就可以找到你所有未保存的文件.

  4. c# winform用sharpGL(OpenGl)解析读取3D模型obj

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/11783026.html 自己写了个简单的类读取解析obj模型,使用导入类,然后new个对象,在 ...

  5. django-模型之(ORM)对象关系映射(一)

    所谓对象关系映射,就是将数据库的一些名字与python中的一些名字相对应,表名-->类名,字段-->属性,操作(增删改查)-->方法.这样,我们就可以通过对Python代码的编辑来对 ...

  6. 在docker中创建使用MySQL,并实现远程连接navicat

    在 docker 中使用 mysql 安装完docker之后,在命令行中输入docker images可以查看自己创建的image(安装下载docker的教程很多了,大家需要可以去查一下就可以了)这里 ...

  7. Java自动化测试框架-07 - TestNG之Factory篇 - 欢快畅游梦幻工厂(详细教程)

    简介 最近忙着装修博客园,没时间更新文章,今天终于抽出时间把上次写的一半的文章给写完了,新的博客园风格,希望大家喜欢.今天继续介绍testng的相关知识--工厂. 工厂允许你动态的创建测试.例如,假设 ...

  8. 第三十七章 POSIX线程(一)

    POSIX线程库相关介绍   与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都有"pthread_"开头   要使用这些函数库,都需要加入头文件"<pth ...

  9. [py2neo]Ubuntu14 安装py2neo失败问题解决

    环境 1.操作系统Ubuntu14 2.py2neo版本4.1 3.python版本python3.4 问题 pip install py2neo==4.1  安装失败,提示: Cannot unin ...

  10. 爬虫之scrapy安装与基本使用

    安装:pip install scrapy基本使用 1. 创建项目:scrapy startproject 项目名 cd 项目名 2. 生成爬虫 1. 创建spider爬虫:scrapy genspi ...