锁所提供的最重要的改进之一就是ReadWriteLock接口和唯一 一个实现它的ReentrantReadWriteLock类。这个类提供两把锁,一把用于读操作和一把用于写操作。同时可以有多个线程执行读操作,但只有一个线程可以执行写操作。当一个线程正在执行一个写操作,不可能有任何线程执行读操作。

参考http://ifeve.com/basic-thread-synchronization-6/#more-7030 做了优化的例子
创建了5个读线程、一个写线程,分别读10次、写3次

PricesInfo

package threadTest.reentrantReadWriteLockTest;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; public class PricesInfo {
private double price1;
private double price2; private ReadWriteLock lock; public PricesInfo() {
this.price1 = 1.0;
this.price2 = 2.0;
this.lock = new ReentrantReadWriteLock();
} public double getPrice1() {
lock.readLock().lock();
System.out.printf("%s : Price1 开始读了!\n" ,Thread.currentThread().getName());
double value = price1;
System.out.printf("%s : Price1 读取完毕 : %f\n"
,Thread.currentThread().getName(),value);
lock.readLock().unlock();
return value;
} public double getPrice2() {
lock.readLock().lock();
System.out.printf("%s : Price2开始读了!\n" ,Thread.currentThread().getName());
double value = price2;
System.out.printf("%s : Price2读取完毕 : %f\n"
,Thread.currentThread().getName(),value);
lock.readLock().unlock();
return value;
} public void setPrices(double price1, double price2) {
lock.writeLock().lock();
System.out.printf("Writer:Attempt to modify the price.\n");
this.price2 = price2;
this.price1 = price1; System.out.printf("Writer:Prices have been modified.\n");
lock.writeLock().unlock(); } }
Reader
package threadTest.reentrantReadWriteLockTest;

public class Reader implements Runnable {
private PricesInfo priceInfo; public Reader(PricesInfo priceInfo) {
this.priceInfo = priceInfo;
} @Override
public void run() {
for (int i = 0; i < 10; i++) {
priceInfo.getPrice1();
priceInfo.getPrice2();
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

Writer

package threadTest.reentrantReadWriteLockTest;

public class Writer implements Runnable {
private PricesInfo pricesInfo; public Writer(PricesInfo pricesInfo) {
this.pricesInfo = pricesInfo;
} @Override
public void run() {
for (int i = 0; i < 3; i++) {
pricesInfo.setPrices((i+1)* 10, (i+1) * 100);
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

main函数

package threadTest.reentrantReadWriteLockTest;

public class App1 {
public static void main(String[] args) {
PricesInfo pricesInfo = new PricesInfo();
Reader[] readers = new Reader[5];
Thread[] threadsReader = new Thread[5];
for (int i = 0; i < 5; i++) {
readers[i] = new Reader(pricesInfo);
threadsReader[i] = new Thread(readers[i]);
}
Writer writer = new Writer(pricesInfo);
Thread threadWriter = new Thread(writer);
for (int i = 0; i < 5; i++) {
threadsReader[i].start();
}
threadWriter.start();
}
}

结果如下

使用ReentrantReadWriteLock,同时可以有多个线程执行读操作,但只有一个线程可以执行写操作

ReentrantReadWriteLock锁例子的更多相关文章

  1. 缓存中使用的ReentrantReadWriteLock锁

    java中提供了lock锁,简便了设计缓存,下面程序主要是使用读写锁的应用.... import java.util.HashMap; import java.util.Map; import jav ...

  2. Java多线程可重入锁例子解析

    “可重入锁”的概念是:自己可以再次获得自己的内部锁.比如有一条线程获得了某个对象的锁,此时这个对象还没有释放,当其再次想获得这个对象的锁的时候还是可以获得的,如果不可锁重入的话,就会造成死锁. cla ...

  3. java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock

    原文:java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock 锁 锁是用来控制多个线程访问共享资源的方式,java中可以使用synch ...

  4. java锁类型

    转载链接在每个锁类型后边 线程锁类型 1.自旋锁 ,自旋,jvm默认是10次吧,有jvm自己控制.for去争取锁 锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchroni ...

  5. 05 JDK1.5 Lock锁

    一.synchronized的再次讨论 使用synchronized关键字来标记一个方法或者代码块,当某个线程调用该对象的synchronized方法或者访问synchronized代码块时, 这个线 ...

  6. Java并发--lock锁详解

    在上一篇文章中我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方 ...

  7. Java并发处理锁 Lock

    在上一篇文章中我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在 java.util.concurrent.locks 包下提供了另外一 ...

  8. 搞定ReentrantReadWriteLock 几道小小数学题就够了

    | 好看请赞,养成习惯 你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it ...

  9. 史上最全java里面的锁

    什么是锁 在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制.锁旨在强制实施互斥排他.并发控制策略. 锁通常需要硬件支持才能有效实施.这 ...

随机推荐

  1. Java BigDecimal进行精确计算

    前言 float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的.然而,它们没有提供完全精确的结果,所以 ...

  2. C-C和指针作业题(第一章)

    在Linux下输入EOF使用Ctrl+D, Windows下输入EOF使用Ctrl+Z 编写一个程序,从标准输入读取几行输入,每行输入都要打印到标准输出上,前面要加上行号,在编写这个程序时要试图让程序 ...

  3. macOS Sierra Git Gui Crash 解决方法

    本篇文章由:http://xinpure.com/macos-sierra-git-gui-crash-solution/ 问题描述 自从升级到 macOS Sierra 10.12 之后,git g ...

  4. HDUOJ---------2255奔小康赚大钱

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  5. xcode 在哪里新建category、protocol等文件

    1.和以前新建新文件一样.2.当然选IOS啦,不过OS X也有这个选项,然后Objctive-C File. 3.在File Type里选就OK啦.

  6. DBA_实践指南系列2_Oracle Erp R12系统安装配置设定Setup(案例)

    2013-12-02 Created By BaoXinjian

  7. fcntl 函数与文件锁

    一.fcntl函数 功能:操纵文件描述符,改变已打开的文件的属性 int fcntl(int fd, int cmd, ... /* arg */ ); cmd的取值可以如下: 复制文件描述符 F_D ...

  8. extjs fileuploadfield default value

    网上有非常多fileupload的demo,最有用的还是官方doc里面的sample. 可是真实业务中.可能会用到改动功能.这个时候就须要在打开的时候,给input框赋初始值. How to give ...

  9. struts2每次访问都会创建一个新的session

    1.第一次 项目在测试过程中,突然发现登陆之后再去访问其他菜单时都会提示未登录: 查看日志之后发现是因为很多次请求时都会自动创建一个新的session,这就费解了, 因为之前也没改动什么session ...

  10. springboot + logback 简介

      转Spring Boot干货系列:(七)默认日志框架配置  分类: Spring Boot(139)  目录(?)[+] 后端编程嘟 2017-04-05 21:53 前言 今天来介绍下sprin ...