package readwritelock;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 基于读写锁的缓存系统
*
* @author tangsi
*
*/
public class CacheSystemWithReadWriteLock {
private Map<String, String> cache = new HashMap<>();
private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// 网上有很多关于用读写锁的缓存系统都没有加volatile关键字,导致用多个线程去执行getData方法时会去数据库查询多次,也就不是真正的缓存系统了,大家可以开多个线程去验证一下
// 至于volatile关键字的作用,大家可以去网上查询
volatile String data = null; // volatile关键字很重要必须加上
public String getData(String key) {
// 先上读锁去缓存中取数据
try {
readWriteLock.readLock().lock();
data = cache.get(key);
if (data != null) {
return data;
} else { // 没有数据则去查询数据库
// 先解除读锁,再上写锁
readWriteLock.readLock().unlock();
try {
readWriteLock.writeLock().lock();
if (data == null) {// 此处应该再次判空,因为有可能多个线程获得写锁
System.out.println("线程"
+ Thread.currentThread().getName() + "查询数据库的值");// 这条语句应该只执行一次,即只查询数据库一次,如果控制台打印多次,则证明查询呢多次数据 库,不 是真正的缓存系统
data = new String("query from database");// 实际上应去查询数据库
cache.put(key, data);
return data;
}
} finally {
// 解除写锁再上读锁
readWriteLock.writeLock().unlock();
readWriteLock.readLock().lock();// 重新上读锁,因为最后finally要解除读锁
}
}
} finally {
readWriteLock.readLock().unlock();
}
return null;
}
}
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 基于读写锁的缓存系统
*
* @author tangsi
*
*/
public class CacheSystemWithReadWriteLock {
private Map<String, String> cache = new HashMap<>();
private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// 网上有很多关于用读写锁的缓存系统都没有加volatile关键字,导致用多个线程去执行getData方法时会去数据库查询多次,也就不是真正的缓存系统了,大家可以开多个线程去验证一下
// 至于volatile关键字的作用,大家可以去网上查询
volatile String data = null; // volatile关键字很重要必须加上
public String getData(String key) {
// 先上读锁去缓存中取数据
try {
readWriteLock.readLock().lock();
data = cache.get(key);
if (data != null) {
return data;
} else { // 没有数据则去查询数据库
// 先解除读锁,再上写锁
readWriteLock.readLock().unlock();
try {
readWriteLock.writeLock().lock();
if (data == null) {// 此处应该再次判空,因为有可能多个线程获得写锁
System.out.println("线程"
+ Thread.currentThread().getName() + "查询数据库的值");// 这条语句应该只执行一次,即只查询数据库一次,如果控制台打印多次,则证明查询呢多次数据 库,不 是真正的缓存系统
data = new String("query from database");// 实际上应去查询数据库
cache.put(key, data);
return data;
}
} finally {
// 解除写锁再上读锁
readWriteLock.writeLock().unlock();
readWriteLock.readLock().lock();// 重新上读锁,因为最后finally要解除读锁
}
}
} finally {
readWriteLock.readLock().unlock();
}
return null;
}
}