版权声明:转载请注明来源 https://blog.csdn.net/qq_24598601/article/details/81872366
一、背景
最近在学习多线程编程,发现实现线程的互斥技术不仅可以用关键字 synchronized,还可以用 java.util.concurrent.locks 包下的读写锁类,使用读写锁比使用关键字的效率更高些,当一个线程加了读锁后其他线程也可以加读锁,但不能加写锁,加了写锁就不能加读锁或写锁。
然后自己用读写锁写了一个简单的缓存系统,完整代码在下面。
二、完整代码
package com.test;
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>();
//new 一个读写锁实例
private ReadWriteLock rwl = new ReentrantReadWriteLock();
/**
* 描述:实现简单的缓存
* @author 欧阳
* @param key
* @return
*/
public Object getData(String key){
rwl.readLock().lock(); //上读锁
Object value = null;
try{
value = cache.get(key);//在缓存中取值
if(value == null){
//当缓存中 key 对应的值时将读锁打开,加上写锁
rwl.readLock().unlock();
rwl.writeLock().lock();
try{
/*
* value = cache.get(key);
* 这一句的作用是保证当多个线程都取相同key的值时只要第
* 一个线程从数据库中拿到了值,其余的线程就不需要再
* 去数据库拿了,从缓冲中拿
*/
value = cache.get(key);
//当缓存中没有时,从数据库中取值
if(value==null){
value = "sqlData";//从数据库中取值;
cache.put(key, value);//将从数据库中取到的值存到缓冲中
//System.out.println(Thread.currentThread().getName() + "从数据库去值");
}
} catch (Exception e) {
e.printStackTrace();
} finally{
//使用try catch finally 是为了防止死锁
//当写入完成后将写锁打开,然后上上读锁
rwl.writeLock().unlock();
}
//上读锁
rwl.readLock().lock();
}
} catch (Exception e) {
e.printStackTrace();
} finally{
//使用try catch finally 是为了防止死锁
//打开读锁
rwl.readLock().unlock();
}
return value;
}
//主方法,测试
public static void main(String[] args) {
final CacheDemo cache = new CacheDemo();
for(int i=0; i<10; i++) {
new Thread(new Runnable() {
public void run() {
cache.getData("a");
}
}).start();
}
//System.out.println("已提交");
}
}