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 那些排它锁只允许在同一时刻只允许一个线程进行访问,读写锁可以允许多个 ... 
随机推荐
- Uipath创建文件夹
			东京IT青年前线 http://www.rpatokyo.com/ Uipath创建文件夹 使用Create Folder进行文件夹的创建 这里可以指定相对路径和绝对路径 如果没有指定文件夹的绝对路径 ... 
- 百万年薪python之路  -- 模块二
			1. 序列化模块 什么是序列化呢? 序列化的本质就是将一种数据结构(如字典.列表)等转换成一个特殊的序列(字符串或者bytes)的过程就叫做序列化. 为什么要有序列化模块? 如果你写入文件中的字符串是 ... 
- vue移动端 实现手机左右滑动入场动画
			app.vue <template> <div id="app"> <transition :name="transitionName&qu ... 
- LeetCode刷题笔记(1)常用知识点
			1.Integer.parseInt(String s, int radix)方法的作用是:将radix进制的字符串s转化成10进制的int型数字并返回. Integer.valueof(String ... 
- 设计模式(二十二)Command模式
			一个类在进行工作时会调用自己或者是其他类的方法,虽然调用结果会反映在对象的状态中,但并不会留下工作的历史记录. 这时,如果我们有一个类,用来表示“请进行这项工作”的“命令”就会方便很多.每一项想做的工 ... 
- SpringCloud之Hystrix服务降级(七)
			Hystrix设计原则 1.防止单个服务的故障,耗尽整个系统服务的容器(比如tomcat)的线程资源,避免分布式环境里大量级联失败.通过第三方客户端访问(通常是通过网络)依赖服务出现失败.拒绝.超时或 ... 
- 在.NET Core 3.0中发布单个EXE文件
			假设我有一个简单的“ Hello World”控制台应用程序,我想发送给朋友来运行.朋友没有安装.NET Core,所以我知道我需要为他构建一个独立的应用程序.很简单,我只需在项目目录中运行以下命令: ... 
- 深度学习框架Tensorflow应用(Google工程师)
			首先在这里给大家分享Google工程师亲授 Tensorflow2.0-入门到进阶教程 有需要的小伙伴可点击进入扣群下载,群内不定期的会分享资料教程,点击直达链接:https://jq.qq.com/ ... 
- Android自定义控件:图形报表的实现(折线图、曲线图、动态曲线图)(View与SurfaceView分别实现图表控件)
			图形报表很常用,因为展示数据比较直观,常见的形式有很多,如:折线图.柱形图.饼图.雷达图.股票图.还有一些3D效果的图表等. Android中也有不少第三方图表库,但是很难兼容各种各样的需求. 如果第 ... 
- MATLAB实例:聚类初始化方法与数据归一化方法
			MATLAB实例:聚类初始化方法与数据归一化方法 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 1. 聚类初始化方法:init_methods.m f ... 
