大纲:

  1. ReadWriteLock接口
  2. ReentrantReadWriteLock
  3. ReentrantReadWriteLock使用

一、ReadWriteLock

public interface ReadWriteLock {
Lock readLock();
Lock writeLock();
}
  1. readLock获得读锁。
  2. writeLock获得写锁。

二、ReentrantReadWriteLock是ReadWriteLock的实现类

  1. ReentrantReadWriteLock内部维护了两个实现Lock接口的内部类ReadLock读锁,与WriteLock写锁。
  2. 仅写锁支持condition。
  3. 锁降级:写锁降级为读锁,获取写锁、获取读锁、释放写锁。
  4. 锁升级:不支持读锁升级为写锁。
  5. 线程间互斥关系:读读共享锁、读写独享锁、写写独享锁
    public class Met {
    ReadWriteLock lock = new ReentrantReadWriteLock();
    public void read(Thread thread){
    try {
    lock.readLock().lock();
    System.out.println(thread.getName()+"read lock");
    for(int i =0;i<10;i++){
    System.out.println(thread.getName()+":"+i);
    }
    } finally {
    System.out.println(Thread.currentThread().getName()+"read unlock");
    lock.readLock().unlock();
    }
    } public void write(Thread thread){
    try {
    lock.writeLock().lock();
    System.out.println(thread.getName()+"write lock");
    for(int i =0;i<10;i++){
    System.out.println(thread.getName()+":"+i);
    }
    } finally {
    System.out.println(Thread.currentThread().getName()+"write unlock");
    lock.writeLock().unlock();
    }
    }
    }
    public class ReadRunnable implements Runnable {
    Met met;
    ReadRunnable(Met met){
    this.met = met;
    }
    @Override
    public void run() {
    met.read(Thread.currentThread());
    }
    }
    public class WriteRunnable implements Runnable {
    Met met;
    WriteRunnable(Met met){
    this.met = met;
    }
    @Override
    public void run() {
    met.write(Thread.currentThread());
    }
    }
    class TestReadWrite {
    public static void main(String[] args) {
    Met met = new Met();
    ReadRunnable read = new ReadRunnable(met);
    WriteRunnable write = new WriteRunnable(met);
    Thread threadread0 = new Thread(read);
    Thread threadread1 = new Thread(read);
    Thread threadwrite0 = new Thread(write);
    threadread0.start();
    threadread1.start();
    threadwrite0.start();
    }
    }

三、ReentrantReadWriteLock使用

  官方demo:更新缓存后的锁降级,保持读锁。

public class CachedData {
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
String data = "未更新"; //缓存数据
volatile boolean isValid; //缓存数据是否有效
void processCachedData(){
readWriteLock.readLock().lock();
System.out.println(Thread.currentThread().getName()+"readLock.lock");
//校验缓存数据是否有效,若无效跟新data,有效直接使用
if(!isValid){
System.out.println(Thread.currentThread().getName()+"readLock.unlock");
readWriteLock.readLock().unlock();
readWriteLock.writeLock().lock();
System.out.println(Thread.currentThread().getName()+"writeLock.lock");
//再次校验
if(!isValid){
data = "已更新";
isValid = true;
System.out.println(Thread.currentThread().getName()+">>>refresh data");
}
//写锁降级为读锁:释放写锁前获取读锁
readWriteLock.readLock().lock();
System.out.println(Thread.currentThread().getName()+"readLock.lock");
System.out.println(Thread.currentThread().getName()+"writeLock.unlock");
//写锁被释放,读锁依旧
readWriteLock.writeLock().unlock();
}
System.out.println(Thread.currentThread().getName()+">>>use data "+data);
System.out.println(Thread.currentThread().getName()+"readLock.unlock");
readWriteLock.readLock().unlock();
}
}
public class ReadWriteRunnable implements Runnable {
CachedData task;
public ReadWriteRunnable(CachedData task){
this.task = task;
}
@Override
public void run() {
task.processCachedData();
}
}
class TestReadWrite {
public static void main(String[] args) {
CachedData task = new CachedData();
ReadWriteRunnable readWriteRunnable = new ReadWriteRunnable(task);
new Thread(readWriteRunnable).start();
new Thread(readWriteRunnable).start();
new Thread(readWriteRunnable).start();
new Thread(readWriteRunnable).start();
new Thread(readWriteRunnable).start();
new Thread(readWriteRunnable).start();
}
}

java多线程-ReadWriteLock的更多相关文章

  1. Java 多线程 ReadWriteLock

    ReadWriteLock是JDK 1.5提供的读写分离锁,可以减少锁竞争.例如,线程A1.A2和A3进行写操作,线程B1.B2和B3进行读操作,如果使用重入锁或者内部锁,那么理论上所有读之间.读与写 ...

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

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

  3. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  4. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  5. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  6. Java多线程系列--“JUC锁”01之 框架

    本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...

  7. java多线程系类:JUC锁:01之框架

    本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--"JUC锁"01之 框架02. Java多线程系列--"JUC锁&q ...

  8. java多线程编程

    一.多线程的优缺点 多线程的优点: 1)资源利用率更好2)程序设计在某些情况下更简单3)程序响应更快 多线程的代价: 1)设计更复杂虽然有一些多线程应用程序比单线程的应用程序要简单,但其他的一般都更复 ...

  9. Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例

    概要 前面对"独占锁"和"共享锁"有了个大致的了解:本章,我们对CountDownLatch进行学习.和ReadWriteLock.ReadLock一样,Cou ...

随机推荐

  1. CodeForces 289B Polo the Penguin and Matrix (数学,中位数)

    题意:给定 n * m 个数,然后每次只能把其中一个数减少d, 问你能不能最后所有的数相等. 析:很简单么,首先这个矩阵没什么用,用一维的存,然后找那个中位数即可,如果所有的数减去中位数,都能整除d, ...

  2. Android 控件在布局中按比例放置[转]

    转自:http://netsky1990.blog.51cto.com/2220666/997452       在Android开发中常用到线性布局LinearLayout对界面进行具体的创建,其中 ...

  3. 编写高质量代码改善C#程序的157个建议——建议149:使用表驱动法避免过长的if和switch分支

    建议149:使用表驱动法避免过长的if和switch分支 随着代码变得复杂,我们很容易被过长的if和switch分支困扰. 一个类枚举类型Week如下: enum Week { Monday, Tue ...

  4. unittest对单个测试类的多种测试执行方法总结

    基于unittest测试框架编写的测试脚本,一般单个测试类下会有多个测试方法,unittest也提供多种测试执行方式,下面就不同方式或者需求一一实操并说明: 一.使用unittest下main()方法 ...

  5. Linux下MySQL表名不区分大小写的设置方法

    MySQL表名不区分大小写的设置方法 在用centox安装mysql后,把项目的数据库移植了过去,发现一些表的数据查不到,排查了一下问题,最后发现是表名的大小写不一致造成的. mysql在window ...

  6. Delphi 实现 图灵机器人API(IDHTTP POST )

    此功能所需的 Key及接口文档,都可以在图灵机器人的官网下载, 小伙伴们需要申请自己的图灵机器人账号. 申请方法请自行百度“图灵机器人”  . 登录账号后,在左侧的[机器人接入],获取需要的信息,记得 ...

  7. js学习日记-对象字面量

    一.对象字面量语法 var person={ name:'小王', age:18, _pri:233 } 成员名称的单引号不是必须的 最后一个成员结尾不要用逗号,不然在某些浏览器中会抛出错误 成员名相 ...

  8. ArcGIS应用——使用Python为图斑连续编号及扩展应用

    为图斑连续编号 在GIS应用中,为图斑连续编号(编号递增)是一项常见的需求,利用ArcGIS,可以方便的实现. Python脚本如下: rec=0 def autoIncrement(): globa ...

  9. PostgreSQL按年月日分组

    Select EXTRACT(year from cast(joindate as timestamp)) as Year, EXTRACT(month from cast(joindate as t ...

  10. centos7 守护进程

    ASP.NET Core应用程序发布linux在shell中运行是正常的.可一但shell关闭网站也就关闭了,所以要配置守护进程, 用的是Supervisor,本文主要记录配置的过程和过程遇到的问题 ...