java并发编程实战手册第二章使用读写锁实现同步数据访问
2015-04-15 18:38
441 查看
[code]Java并发编程实战手册第二章关于锁的问题。
2.6使用读写锁实现同步数据访问
通过本范例学习ReadWriteLock和实现类,ReentrantReadWriteLock,该类有两个锁一个是读操作锁,一个是写操作锁。读操作锁可以允许多个线程同时访问,写操作锁只允许一个线程进行。当写操作执行的时候,读操作不能执行
1. 创建PriceInfo,Reader,Writer,Main.
1. PriceInfo.java
[code]1. PriceInfo.java package cn.fans.chapter2.six; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * * @author fcs * @date 2015-4-12 * 描述:使用读写锁实现同步访问 * 说明:使用ReadWriteLock接口。 */ public class PricesInfo { private double price1; private double price2; private ReadWriteLock lock; public PricesInfo(){ price1 = 1.0; price2 = 2.0; lock = new ReentrantReadWriteLock(); } /** * * 作者:fcs * 描述:使用锁机制进行读操作 * 说明: * 返回:price1 * 参数: * 时间:2015-4-12 */ public double getPrice1(){ double value; lock.readLock().lock(); try{ value = price1; System.out.printf("%s: price 1 : %f\n",Thread.currentThread().getName(),price1); }finally{ lock.readLock().unlock(); } return value; } /** * * 作者:fcs * 描述:使用锁机制进行读操作 * 说明: * 返回:price2 * 参数: * 时间:2015-4-12 */ public double getPrice2(){ double value; lock.readLock().lock(); try{ value = price2; System.out.printf("%s Price 2 : %f\n ",Thread.currentThread().getName(),price2); }finally{ lock.readLock().unlock(); } return value; } /** * * 作者:fcs * 描述:使用锁机制进行写操作 * 说明: * 返回: * 参数:price1, price2 * 时间:2015-4-12 */ public void setPrice(double price1,double price2){ lock.writeLock().lock(); System.out.printf("Writer: Attempt to modify the prices.\n"); try{ this.price1 = price1; this.price2 = price2; }finally{ lock.writeLock().unlock(); System.out.println("Writer:price have been modified."); } } }
[code]package cn.fans.chapter2.six; /** * * @author fcs * @date 2015-4-12 * 描述:读线程 * 说明: */ public class Reader implements Runnable { private PricesInfo pricesInfo; public Reader(PricesInfo pricesInfo) { this.pricesInfo = pricesInfo; } @Override public void run() { for(int i =0;i<10;i++){ pricesInfo.getPrice1(); pricesInfo.getPrice2(); } } }
[code]package cn.fans.chapter2.six; /** * * @author fcs * @date 2015-4-12 * 描述:写线程 * 说明: */ public class Writer implements Runnable { private PricesInfo pricesInfo; public Writer(PricesInfo pricesInfo) { this.pricesInfo = pricesInfo; } /** * 循环修改两个价格5次,每次修改后线程将休眠2秒钟 */ @Override public void run() { for(int i=0;i< 5;i++){ pricesInfo.setPrice(Math.random()*10, Math.random()*10); try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } } }
[code]package cn.fans.chapter2.six; public class Main { public static void main(String[] args) { PricesInfo pricesInfo = new PricesInfo(); Reader readers[] = new Reader[5]; Thread treader [] = new Thread[5]; for(int i =0;i<5;i++){ readers [i] = new Reader(pricesInfo); treader[i] = new Thread(readers[i]); } Writer writer = new Writer(pricesInfo); Thread wthread = new Thread(writer); for(int i = 0;i < 5;i++){ treader[i].start(); } wthread.start(); } }
创建5个读线程,一个写线程,读线程不互斥,写线程写的时候,读线程读到的信息必须是写线程写完后的新数据。这里如果按照书上的代码,可能会出现非常令人迷惑的输出,关键在与Writer线程中的run方法多了两条输出语句,这两条应该在priceInfo中的setPrice方法中的,我在并发编程网上看到有人说要放在这里,同样csdn上也获得了相同的指导,在实际的运行过程中才跟书上的一致。
深入分析就是Writer线程是使用for循环进行写入的,也就是说在for循环中的两条输出语句中间执行priceinfo.setPrice方法,是有延迟的,导致每次修改前后两条输出语句并不是连续输出的,这是因为在输出第一条语句的时候,写线程正在获取锁,其他读线程可能正在读写线程上一次修改的值,当输出第二条语句的时候,有的读线程读到新的值,而有的读到旧的值。这就出现了一种幻觉,认为读线程读到了脏数据。所以应该将这两条放到setPrice中的lock(),和unlock()方法下。这样才会输出两条连续的提示语句,然后读线程会在输出语句后读出一致的值。
相关文章推荐
- 使用读写锁实现同步数据访问
- 【Java并发编程实战】– 使用读写锁实现同步数据访问 lock_2
- oracle_fdw的使用:从PostgreSQL中访问Oracle数据库,实现数据库数据的同步
- Java并发学习之十五——使用读写锁同步数据访问
- Java并发编程-09-使用读写锁同步数据访问
- 项目中遇到通过使用路由策略实现主从数据库访问数据不同步的问题
- java读写锁实现数据同步访问
- IONIC 中使用拦截功能来实现API接口访问的数据缓存
- IONIC 中使用拦截功能来实现API接口访问的数据缓存
- 代码笔记 | 多线程使用queue模块同步访问共享数据
- jQuery的deferred对象使用详解——实现ajax同步请求数据
- java多线程-使用ReadWriteLock同步数据访问
- 使用hyperpacer实现监控数据的同步收集
- 使用databus实现oracle和内存数据库redis之间的数据同步
- 使用NFS文件系统实现数据同步
- 使用DB查询分析器实现异构数据源中数据表的相互访问
- 使用DB查询分析器实现异构数据源中数据表的相互访问
- 使用 Tungsten Replicator4 实现 mysql -- > mongodb 数据同步
- 使用merge 加 dblink 实现内网中的两个数据同步
- 使用SharedPreferences实现Activity和Service之间数据同步问题