锁机制带来的最有意义的改进是提供了ReadWriteLock接口及其实现类ReentrantReadWriteLock。

这个类有2个锁,一个针对读操作另一个针对写操作。

可以有多个线程使用读操作,但是只有一个线程使用写操作。

当一个线程做写操作时,不能有任何线程做读操作。

本例中,我们将学习如何通过ReadWriteLock接口实现一个对2个产品价格的访问进行控制。

PricesInfo.java
package com.dylan.thread.ch2.c05.task;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; /**
* This class simulates the store of two prices. We will
* have a writer that stores the prices and readers that
* consult this prices
*
*/
public class PricesInfo { /**
* The two prices
*/
private double price1;
private double price2; /**
* Lock to control the access to the prices
*/
private ReadWriteLock lock; /**
* Constructor of the class. Initializes the prices and the Lock
*/
public PricesInfo(){
price1=1.0;
price2=2.0;
lock=new ReentrantReadWriteLock();
} /**
* Returns the first price
* @return the first price
*/
public double getPrice1() {
lock.readLock().lock();
double value=price1;
lock.readLock().unlock();
return value;
} /**
* Returns the second price
* @return the second price
*/
public double getPrice2() {
lock.readLock().lock();
double value=price2;
lock.readLock().unlock();
return value;
} /**
* Establish the prices
* @param price1 The price of the first product
* @param price2 The price of the second product
*/
public void setPrices(double price1, double price2) {
lock.writeLock().lock();
this.price1=price1;
this.price2=price2;
lock.writeLock().unlock();
}
}
Reader.java
package com.dylan.thread.ch2.c05.task;

/**
* This class implements a reader that consults the prices
*
*/
public class Reader implements Runnable { /**
* Class that stores the prices
*/
private PricesInfo pricesInfo; /**
* Constructor of the class
* @param pricesInfo object that stores the prices
*/
public Reader (PricesInfo pricesInfo){
this.pricesInfo=pricesInfo;
} /**
* Core method of the reader. Consults the two prices and prints them
* to the console
*/
@Override
public void run() {
for (int i=0; i<10; i++){
System.out.printf("%s: Price 1: %f\n",Thread.currentThread().getName(),pricesInfo.getPrice1());
System.out.printf("%s: Price 2: %f\n",Thread.currentThread().getName(),pricesInfo.getPrice2());
}
} }
Writer.java
package com.dylan.thread.ch2.c05.task;

/**
* This class implements a writer that establish the prices
*
*/
public class Writer implements Runnable { /**
* Class that stores the prices
*/
private PricesInfo pricesInfo; /**
* Constructor of the class
* @param pricesInfo object that stores the prices
*/
public Writer(PricesInfo pricesInfo){
this.pricesInfo=pricesInfo;
} /**
* Core method of the writer. Establish the prices
*/
@Override
public void run() {
for (int i=0; i<3; i++) {
System.out.printf("Writer: Attempt to modify the prices.\n");
pricesInfo.setPrices(Math.random()*10, Math.random()*8);
System.out.printf("Writer: Prices have been modified.\n");
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} }
Main.java
package com.dylan.thread.ch2.c05.core;

import com.dylan.thread.ch2.c05.task.PricesInfo;
import com.dylan.thread.ch2.c05.task.Reader;
import com.dylan.thread.ch2.c05.task.Writer; /**
* Main class of the example
*
*/
public class Main { /**
* Main class of the example
* @param args
*/
public static void main(String[] args) { // Creates an object to store the prices
PricesInfo pricesInfo=new PricesInfo(); Reader readers[]=new Reader[5];
Thread threadsReader[]=new Thread[5]; // Creates five readers and threads to run them
for (int i=0; i<5; i++){
readers[i]=new Reader(pricesInfo);
threadsReader[i]=new Thread(readers[i]);
} // Creates a writer and a thread to run it
Writer writer=new Writer(pricesInfo);
Thread threadWriter=new Thread(writer); // Starts the threads
for (int i=0; i<5; i++){
threadsReader[i].start();
}
threadWriter.start(); } }

运行结果:

Thread-0: Price 1: 1.000000
Thread-3: Price 1: 1.000000
Thread-3: Price 2: 2.000000
Thread-3: Price 1: 1.000000
Thread-3: Price 2: 2.000000
Thread-3: Price 1: 1.000000
Thread-3: Price 2: 2.000000
Thread-3: Price 1: 1.000000
Thread-3: Price 2: 2.000000
Thread-3: Price 1: 1.000000
Thread-3: Price 2: 2.000000
Writer: Attempt to modify the prices.
Thread-3: Price 1: 1.000000
Thread-3: Price 2: 1.280423
Thread-3: Price 1: 3.047936

...

Java并发编程实例--17.使用read/write锁同步数据访问的更多相关文章

  1. Java并发编程原理与实战十一:锁重入&自旋锁&死锁

    一.锁重入 package com.roocon.thread.t6; public class Demo { /* 当第一个线程A拿到当前实例锁后,进入a方法,那么,线程A还能拿到被当前实例所加锁的 ...

  2. 【Java并发编程实战】----- AQS(四):CLH同步队列

    在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形.其主要从两方面进行了改造:节点的结构与节点等待机制.在结构上引入了头 ...

  3. java并发编程的艺术(一)---锁的基本属性

    本文来源于翁舒航的博客,点击即可跳转原文观看!!!(被转载或者拷贝走的内容可能缺失图片.视频等原文的内容) 若网站将链接屏蔽,可直接拷贝原文链接到地址栏跳转观看,原文链接:https://www.cn ...

  4. 【Java并发编程实战】—– AQS(四):CLH同步队列

    在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形. 其主要从双方面进行了改造:节点的结构与节点等待机制.在结构上引入了 ...

  5. Java并发编程实战.笔记十一(非阻塞同步机制)

    关于非阻塞算法CAS. 比较并交换CAS:CAS包含了3个操作数---需要读写的内存位置V,进行比较的值A和拟写入的新值B.当且仅当V的值等于A时,CAS才会通过原子的方式用新值B来更新V的值,否则不 ...

  6. java并发编程JUC第九篇:CountDownLatch线程同步

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue.LinkedBlockingQueue.Priorit ...

  7. Java并发编程实例(synchronized)

    此处用一个小程序来说明一下,逻辑是一个计数器(int i):主要的逻辑功能是,如果同步监视了资源i,则不输出i的值,但如果没有添加关键字synchronized,因为是两个线程并发执行,所以会输出i的 ...

  8. java并发编程实战《三》互斥锁(上)

    互斥锁(上):解决原子性问题 原子性问题的源头是线程切换,操作系统做线程切换是依赖 CPU 中断的,所以禁止 CPU 发生中断就能够禁止线程切换. 在早期单核 CPU 时代,这个方案的确是可行的,而且 ...

  9. Java并发编程实战(3)- 互斥锁

    我们在这篇文章中主要讨论如何使用互斥锁来解决并发编程中的原子性问题. 目录 概述 互斥锁模型 互斥锁简易模型 互斥锁改进模型 Java世界中的互斥锁 synchronized中的锁和锁对象 synch ...

  10. Java并发编程学习:线程安全与锁优化

    本文参考<深入理解java虚拟机第二版> 一.什么是线程安全? 这里我借<Java Concurrency In Practice>里面的话:当多个线程访问一个对象,如果不考虑 ...

随机推荐

  1. 【水一篇】骚操作之net 6的winform启动的同时启动Net 6 WebApi【同一套代码】

    引言 有段时间没有写博客了,不知道写什么,加上最近一直在玩单片机方面的东西,所以有一些懈怠.首先呢,为什么会有这么一个问题,是在一个QQ群里,有看到有人提问,能不能在启动Winform的同时去启动一个 ...

  2. [转帖]深度硬核文:Nginx的301重定向处理过程分析

    https://zhuanlan.zhihu.com/p/84539204 本文首发于公众号:js-mindmap 一,序言 "晚上九点,办公室里烟雾缭绕,工作进度依然没有什么进展.王二胖打 ...

  3. [转帖]TIDB - 使用 Dumpling 和 TiDB Lightning 迁移Mysql数据至TIDB中

    一.TiDB Lightning介绍 TiDB Lightning 是一个将全量数据高速导入到 TiDB 集群的工具,目前支持 Mydumper 或 CSV 输出格式的数据源.你可以在以下两种场景下使 ...

  4. [转帖]elasticsearch-create-enrollment-tokenedit

    https://www.elastic.co/guide/en/elasticsearch/reference/current/create-enrollment-token.html The ela ...

  5. [转帖]Web性能优化工具WebPageTest(三)——本地部署(Windows 7版本)

    http://www.zlprogram.com/Show/30/30117.shtml 这次先能够使用PC端的浏览器测试,首先需要下载官方的发布版本"WebPageTest 3.0&quo ...

  6. [转帖]linux性能优化-内存回收

    linux文件页.脏页.匿名页 缓存和缓冲区,就属于可回收内存.它们在内存管理中,通常被叫做文件页(File-backed Page). 通过内存映射获取的文件映射页,也是一种常见的文件页.它也可以被 ...

  7. CS5280H 无网络安装KVM虚拟机的过程

    背景 信创海光机器 想进行虚拟化 自带了银河麒麟V10 SP1的操作系统. 但是没有安装virt-manager等工具 会议室里面的网口又都坏了. 所以准备挑战一下无网络安装KVM. 过程1 第一步. ...

  8. WebAssembly入门笔记[1]:与JavaScript的交互

    前一阵子利用Balazor开发了一个NuGet站点,对WebAssembly进行了初步的了解,觉得挺有意思.在接下来的一系列文章中,我们将通过实例演示的方式介绍WebAssembly的一些基本概念和编 ...

  9. 袋鼠云数栈产品中 AI+ 实现原理剖析

    生产力工具 + AI 是不可逆转的趋势,慢慢的大模型能力通过 AI Agent 落地的工程化能力也开始趋于成熟.作为大数据产品的数栈也必然是需要借助 AI 能力提升产品竞争力. 去年 12 月,我们在 ...

  10. zookeeper的Leader选举源码解析

    作者:京东物流 梁吉超 zookeeper是一个分布式服务框架,主要解决分布式应用中常见的多种数据问题,例如集群管理,状态同步等.为解决这些问题zookeeper需要Leader选举进行保障数据的强一 ...