读写锁ReentrantReadWriteLock概述

读写锁ReentrantReadWriteLock,使用它比ReentrantLock效率更高。

读写锁表示两个锁,一个是读操作相关的锁,称为共享锁;另一个是写操作相关的锁,称为排他锁。

1、读和读之间不互斥,因为读操作不会有线程安全问题

2、写和写之间互斥,避免一个写操作影响另外一个写操作,引发线程安全问题

3、读和写之间互斥,避免读操作的时候写操作修改了内容,引发线程安全问题

多个Thread可以同时进行读取操作,但是同一时刻只允许一个Thread进行写入操作。

读操作和读操作共享

请看例子

ThreadDomain44类和main方法

public class ThreadDomain44 extends ReentrantReadWriteLock
{
public void read()
{
try
{
readLock().lock();
System.out.println(Thread.currentThread().getName() + "获得了读锁, 时间为" +
System.currentTimeMillis());
Thread.sleep(10000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
readLock().unlock();
}
} public static void main(String[] args)
{
final ThreadDomain44 td = new ThreadDomain44();
Runnable readRunnable = new Runnable()
{
public void run()
{
td.read();
}
};
Thread t0 = new Thread(readRunnable);
Thread t1 = new Thread(readRunnable);
t0.start();
t1.start();
}
}

输出结果如下

Thread-0获得了读锁, 时间为1564018325618
Thread-1获得了读锁, 时间为1564018325618

尽管加了Thread.sleep(10000);两个线程几乎同时执行lock()后面的方法。说明readLock().lock()允许多个线程执行并且能提高执行效率。

写操作和写操作互斥

请看例子

public class ThreadDomain45 extends ReentrantReadWriteLock {
public void write()
{
try
{
writeLock().lock();
System.out.println(Thread.currentThread().getName() + "获得了写锁, 时间为" +
new Date());
Thread.sleep(10000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
writeLock().unlock();
}
} public static void main(String[] args)
{
final ThreadDomain45 td = new ThreadDomain45();
Runnable readRunnable = new Runnable()
{
public void run()
{
td.write();
}
};
Thread t0 = new Thread(readRunnable);
Thread t1 = new Thread(readRunnable);
t0.start();
t1.start();
}
}

输出结果

Thread-1获得了写锁, 时间为Tue Jul 30 11:26:21 CST 2019
Thread-0获得了写锁, 时间为Tue Jul 30 11:26:31 CST 2019

可以看到,后获得锁的Thread-0等待了十秒,说明写和写互斥

读操作和写操作互斥/写操作和读操作互斥

例子如下

public class ThreadDomain46 extends ReentrantReadWriteLock {
public void write()
{
try
{
writeLock().lock();
System.out.println(Thread.currentThread().getName() + "获得了写锁, 时间为" +
new Date());
Thread.sleep(10000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
writeLock().unlock();
}
} public void read()
{
try
{
readLock().lock();
System.out.println(Thread.currentThread().getName() + "获得了读锁, 时间为" +
new Date());
Thread.sleep(10000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
finally
{
readLock().unlock();
}
} public static void main(String[] args)
{
final ThreadDomain46 td = new ThreadDomain46();
Runnable readRunnable = new Runnable()
{
public void run()
{
td.read();
}
};
Runnable writeRunnable = new Runnable()
{
public void run()
{
td.write();
}
};
Thread t0 = new Thread(readRunnable);
Thread t1 = new Thread(writeRunnable);
t0.start();
t1.start();
}
}

输出结果如下

Thread-0获得了读锁, 时间为Tue Jul 30 11:49:15 CST 2019
Thread-1获得了写锁, 时间为Tue Jul 30 11:49:26 CST 2019

可以看到Thread-0获得读锁执行完10s后Thread-1才获得了写锁,说明读操作和写操作互斥。

另一种输出结果如下

Thread-1获得了写锁, 时间为Tue Jul 30 14:14:07 CST 2019
Thread-0获得了读锁, 时间为Tue Jul 30 14:14:17 CST 2019

可以看到Thread-1获得写锁执行完10s后Thread-0才获得了读锁,说明写操作和读操作互斥。

Java多线程(八):ReentrantReadWriteLock的更多相关文章

  1. Java多线程——<八>多线程其他概念

    一.概述 到第八节,就把多线程基本的概念都说完了.把前面的所有文章加连接在此: Java多线程——<一>概述.定义任务 Java多线程——<二>将任务交给线程,线程声明及启动 ...

  2. java多线程(八)-死锁问题和java多线程总结

    为了防止对共享受限资源的争夺,我们可以通过synchronized等方式来加锁,这个时候该线程就处于阻塞状态,设想这样一种情况,线程A等着线程B完成后才能执行,而线程B又等着线程C,而线程C又等着线程 ...

  3. java多线程:ReentrantReadWriteLock读写锁使用

    Lock比传统的线程模型synchronized更多的面向对象的方式.锁和生活似,应该是一个对象.两个线程运行的代码片段要实现同步相互排斥的效果.它们必须用同一个Lock对象. 读写锁:分为读锁和写锁 ...

  4. 【Java多线程】ReentrantReadWriteLock

    概述 ReentrantReadWriteLock是Lock的另一种实现方式,ReentrantLock是一个排他锁,同一时间只允许一个线程访问,而ReentrantReadWriteLock允许多个 ...

  5. Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock

    概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...

  6. Java多线程(五) Lock接口,ReentranctLock,ReentrantReadWriteLock

    在JDK5里面,提供了一个Lock接口.该接口通过底层框架的形式为设计更面向对象.可更加细粒度控制线程代码.更灵活控制线程通信提供了基础.实现Lock接口且使用得比较多的是可重入锁(Reentrant ...

  7. java多线程系列(八)---CountDownLatch和CyclicBarrie

    CountDownLatch 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 java多线 ...

  8. Java多线程——线程八锁案例分析

    Java多线程——线程八锁案例分析 摘要:本文主要学习了多线程并发中的一些案例. 部分内容来自以下博客: https://blog.csdn.net/dyt443733328/article/deta ...

  9. Java 多线程基础(八)线程让步

    Java 多线程基础(八)线程让步 yield 一.yield 介绍 yield()的作用是让步.它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权:但是,并 ...

  10. java多线程7:ReentrantReadWriteLock

    真实的多线程业务开发中,最常用到的逻辑就是数据的读写,ReentrantLock虽然具有完全互斥排他的效果(即同一时间只有一个线程正在执行lock后面的任务), 这样做虽然保证了实例变量的线程安全性, ...

随机推荐

  1. 感知机算法及BP神经网络

    简介:感知机在1957年就已经提出,可以说是最为古老的分类方法之一了.是很多算法的鼻祖,比如说BP神经网络.虽然在今天看来它的分类模型在很多数时候泛化能力不强,但是它的原理却值得好好研究.先学好感知机 ...

  2. Android5.0以下drawable tag vector错误的解决办法(转发)

    Android5.0以下drawable tag vector错误的解决办法 在Androi 5.0以下的设备可能会报这样的错误: Caused by: org.xmlpull.v1.XmlPullP ...

  3. PAT 甲级 1027 Colors in Mars (20 分)(简单,进制转换)

    1027 Colors in Mars (20 分)   People in Mars represent the colors in their computers in a similar way ...

  4. 工具的更新换代 总是要折腾一下Windows10下Java Web 开发环境的配置

    Windows10下Java Web 开发环境的配置 由于经常性遗忘,所以整理一下 Java Web 开发环境的搭建与配置,利人利己 主要分为以下几步,需要可以挑着看 Windows下 JDK 的下载 ...

  5. js 基本类型与引用类型的存储

    js的变量类型分为基本数据类型和引用数据类型 7种基本数据类型:null, undefined, number, boolean, string(大多数语言中string属于引用数据类型,而在js中它 ...

  6. Css3 伪元素

    伪元素---用于向某些选择器设置特殊的效果 语法:元素::伪元素 (element::pseudo-element) 兼容性:IE9+ FireFox4+ Chrome Safari Opera fi ...

  7. Flutter 底部的renderflex溢出

    一开始直接使用Scaffold布局,body:new Column  然后模拟器会提示捕获异常: 然后百度了一下Flutter的溢出问题,发现解决办法是使用SingleChildScrollView包 ...

  8. 100% 加速 WebSAMS 3.0 (轉載)

    今日已經是WebSAMS Upgrade 的最後一日,已經有99.8% 學校成功upgrade WebSAMS 3.0.但有學校向我們反映WebSAMS 3.0 比2.0 慢,經過我們的Enginee ...

  9. ps命令入门使用指南

    声明:本文算不上原创,主要是参考和整理了该博客ps命令详解 Shell 命令: ps [options] [--help] ps 常用参数: l 长格式输出: u 按用户名和启动时间的顺序来显示进程: ...

  10. Docker存储容易忽略的使用细节

    一.Docker容器使用前其实有个非常重要的步骤就是规划好部署的磁盘区域,因为docker容器默认存储的路径是在/var/lib/docker的根目录内,随着使用时间越长部署的内容越多,基本的根目录的 ...