您的位置:首页 > 编程语言 > Java开发

Java5并发库之锁(二)——读写锁技术的妙用

2013-04-23 17:01 330 查看
读写锁:读写锁分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥,这是由JVM自己控制的,我们只要上好相应的锁即可。如果代码是只读数据,可以很多人同时读,但不能同时写,那就需要上读锁;如果代码是修改数据,只能有一个人在写,且不能在写的时候读,就需要上写锁。总之,读的时候上读锁,写的时候上写锁。

1- 1 一个读写锁的例子

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class CacheDemo {
private Map<String, Object> cache = new HashMap<String, Object>();
public static void main(String[] args) {

}
private ReadWriteLock rwl = new ReentrantReadWriteLock();
public  Object getData(String key){
rwl.readLock().lock();
Object value = null;
try{
value = cache.get(key);
if(value == null){
rwl.readLock().unlock();
rwl.writeLock().lock();
try{
if(value==null){
value = "aaaa";//实际失去queryDB();
}
}finally{
rwl.writeLock().unlock();
}
rwl.readLock().lock();
}
}finally{
rwl.readLock().unlock();
}
return value;
}
}


程序运行的结果:





从运行结果可以看到,当一个线程写的时候,其它的线程不允许写;而读的时候,允许多个线程同时读,且读到的数据是一致的。

在Hibernate中会有代码1-2 这样的代码:

代码1-2

User user = session.load(id,User.class);


代码1-3

User user = session.get(id,User.class);

那么代码1-2 与 1-3 有什么区别呢?

代码1-2 ,不管数据库中有没有记录,它都返回一个user对象,它是一个代理(是user的子类,可以被当做user用),是一个假的,不是一个真正的user对象。如下图:





代码1-3 ,是直接到数据库中把对象给“抓”出来,如果没有“抓”到,返回的值是NULL(空)。看看下面的这道面试题:

一个缓存系统(可以装很多的对象)的例子

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class CacheDemo {
private Map<String, Object> cache = new HashMap<String, Object>();//定义缓存
public static void main(String[] args) {

}
private ReadWriteLock rwl = new ReentrantReadWriteLock();//定义一个读写锁
/*
取数据的方法,检查内部是否有key这个数据,如果有,直接传递给程序;没有,去数据库查,
查到之后存到缓存的内存中。  下次,再有程序找该数据时,直接将缓存中的数据传给程序,不需要访问数据库
*/
public  Object getData(String key){
rwl.readLock().lock();//首先都上读锁*(都可以读),加锁,实现多个线程的访问
Object value = null;//注意:在try{}catch(){}中不能定义变量
try{
value = cache.get(key);//在cache中取数据
if(value == null){
rwl.readLock().unlock();//释放读锁**(注意*的对应关系)
rwl.writeLock().lock();//上写锁***
try{
if(value==null){//当其它的线程检查不为空,就不用再写
value = "aaaa";//实际是去queryDB();
}
}finally{
rwl.writeLock().unlock();//释放写锁***
}
rwl.readLock().lock();//恢复读锁**
}
}finally{
rwl.readLock().unlock();//释放读锁*
}
return value;
}
}


注意代码

if(value==null){//当其它的线程检查不为空,就不用再写
value = "aaaa";//实际是去queryDB();
}

当其它的线程检查缓存中有数据时,就不再进行写的操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java读写锁