问题描述
- 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;
}finally{
lock.readLock().unlock();
}return value;
}
/**
- 作者:fcs
- 描述:使用锁机制进行读操作
- 说明:
- 返回:price2
- 参数:
- 时间:2015-4-12
*/
public double getPrice2(){
double value;
lock.readLock().lock();
try{
value = price2;
}finally{
lock.readLock().unlock();
}return value;
}
/**
- 作者:fcs
- 描述:使用锁机制进行写操作
- 说明:
- 返回:
- 参数:price1, price2
- 时间:2015-4-12
*/
public void setPrice(double price1,double price2){
lock.writeLock().lock();
try{
this.price1 = price1;
this.price2 = price2;
}finally{
lock.writeLock().unlock();
}
}
}
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++){
System.out.printf("%s: price 1 : %fn",Thread.currentThread().getName(),pricesInfo.getPrice1());
System.out.printf("%s Price 2 : %fn ",Thread.currentThread().getName(),pricesInfo.getPrice2());
}
}
}
package cn.fans.chapter2.six;
import java.util.concurrent.TimeUnit;
/**
- @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++){
System.out.printf("Writer: Attempt to modify the prices.n");
pricesInfo.setPrice(Math.random()*10, Math.random()*10);
System.out.println("Writer:price have been modified.");
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
- 循环修改两个价格5次,每次修改后线程将休眠2秒钟
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(); }
}
这是java并发实战手册第二章的代码,但是在我机子上运行的结果与书上不一样,写锁好像不起作用,我重新检查了代码并且运行了几遍,感觉总像读线程读了脏数据,希望有人能指点迷津。共同进步
解决方案
从原理上来说,你这打印的情况是存在的
public double getPrice1(){
double value;
lock.readLock().lock();//加锁
try{
value = price1; //这里是1.0,
}finally{
lock.readLock().unlock();//锁释放
}
return value;//value是1.0,这时候还没有返回,其他线程,比如写进程获取锁改变了price1=0.97,然后其他线程获取锁,打印了price1 0.97。
这时该线程返回,值是1.0
}
把这种代码换一下顺序
public double getPrice1(){
lock.readLock().lock();//加锁
try{
return price1; //这里是1.0,
}finally{
lock.readLock().unlock();//锁释放
}
}
解决方案二:
哦,好的,不过我在并发编程网上找到答案了,给分。
解决方案三:
哦,好的,不过我在并发编程网上找到答案了,给分。