读/写锁的实现和应用(高并发状态下的map实现)
程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写(译者注:也就是说:读-读能共存,读-写不能共存,写-写不能共存)。这就需要一个读/写锁来解决这个问题。
按照上面的叙述,简单的实现出一个读/写锁
public class ReadWriteLock{
private int readers = ;
private int writers = ;
private int writeRequests = ;
public synchronized void lockRead()
throws InterruptedException{
while(writers > || writeRequests > ){
wait();
}
readers++;
}
public synchronized void unlockRead(){
readers--;
notifyAll();
}
public synchronized void lockWrite()
throws InterruptedException{
writeRequests++;
while(readers > || writers > ){
wait();
}
writeRequests--;
writers++;
}
public synchronized void unlockWrite()
throws InterruptedException{
writers--;
notifyAll();
}
}
ReadWriteLock类中,读锁和写锁各有一个获取锁和释放锁的方法。
可重入的ReadWriteLock的完整实现
下面是完整的ReadWriteLock实现。为了便于代码的阅读与理解,简单对上面的代码做了重构。重构后的代码如下。
public class ReadWriteLock{
private Map<Thread, Integer> readingThreads =
new HashMap<Thread, Integer>();
private int writeAccesses = ;
private int writeRequests = ;
private Thread writingThread = null;
public synchronized void lockRead()
throws InterruptedException{
Thread callingThread = Thread.currentThread();
while(! canGrantReadAccess(callingThread)){
wait();
}
readingThreads.put(callingThread,
(getReadAccessCount(callingThread) + ));
}
private boolean canGrantReadAccess(Thread callingThread){
if(isWriter(callingThread)) return true;
if(hasWriter()) return false;
if(isReader(callingThread)) return true;
if(hasWriteRequests()) return false;
return true;
}
public synchronized void unlockRead(){
Thread callingThread = Thread.currentThread();
if(!isReader(callingThread)){
throw new IllegalMonitorStateException(
"Calling Thread does not" +
" hold a read lock on this ReadWriteLock");
}
int accessCount = getReadAccessCount(callingThread);
if(accessCount == ){
readingThreads.remove(callingThread);
} else {
readingThreads.put(callingThread, (accessCount -));
}
notifyAll();
}
public synchronized void lockWrite()
throws InterruptedException{
writeRequests++;
Thread callingThread = Thread.currentThread();
while(!canGrantWriteAccess(callingThread)){
wait();
}
writeRequests--;
writeAccesses++;
writingThread = callingThread;
}
public synchronized void unlockWrite()
throws InterruptedException{
if(!isWriter(Thread.currentThread()){
throw new IllegalMonitorStateException(
"Calling Thread does not" +
" hold the write lock on this ReadWriteLock");
}
writeAccesses--;
if(writeAccesses == ){
writingThread = null;
}
notifyAll();
}
private boolean canGrantWriteAccess(Thread callingThread){
if(isOnlyReader(callingThread)) return true;
if(hasReaders()) return false;
if(writingThread == null) return true;
if(!isWriter(callingThread)) return false;
return true;
}
private int getReadAccessCount(Thread callingThread){
Integer accessCount = readingThreads.get(callingThread);
if(accessCount == null) return ;
return accessCount.intValue();
}
private boolean hasReaders(){
return readingThreads.size() > ;
}
private boolean isReader(Thread callingThread){
return readingThreads.get(callingThread) != null;
}
private boolean isOnlyReader(Thread callingThread){
return readingThreads.size() == &&
readingThreads.get(callingThread) != null;
}
private boolean hasWriter(){
return writingThread != null;
}
private boolean isWriter(Thread callingThread){
return writingThread == callingThread;
}
private boolean hasWriteRequests(){
return this.writeRequests > ;
}
}
应用:线程安全并且高并发状态下的map实现
class RWDictionary {
private final Map<String, Data> m = new TreeMap<String, Data>();
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();
public Data get(String key) {
r.lock();
try { return m.get(key); }
finally { r.unlock(); }
}
public String[] allKeys() {
r.lock();
try { return m.keySet().toArray(); }
finally { r.unlock(); }
}
public Data put(String key, Data value) {
w.lock();
try { return m.put(key, value); }
finally { w.unlock(); }
}
public void clear() {
w.lock();
try { m.clear(); }
finally { w.unlock(); }
}
}
读/写锁的实现和应用(高并发状态下的map实现)的更多相关文章
- php高并发状态下文件的读写
php高并发状态下文件的读写 背景 1.对于PV不高或者说并发数不是很大的应用,不用考虑这些,一般的文件操作方法完全没有问题 2.如果并发高,在我们对文件进行读写操作时,很有可能多个进程对进一文件 ...
- C++高并发场景下读多写少的解决方案
C++高并发场景下读多写少的解决方案 概述 一谈到高并发的解决方案,往往能想到模块水平拆分.数据库读写分离.分库分表,加缓存.加mq等,这些都是从系统架构上解决.单模块作为系统的组成单元,其性能好坏也 ...
- C++高并发场景下读多写少的优化方案
概述 一谈到高并发的优化方案,往往能想到模块水平拆分.数据库读写分离.分库分表,加缓存.加mq等,这些都是从系统架构上解决.单模块作为系统的组成单元,其性能好坏也能很大的影响整体性能,本文从单模块下读 ...
- C# 防止同时调用=========使用读写锁三行代码简单解决多线程并发的问题
http://www.jb51.net/article/99718.htm 本文主要介绍了C#使用读写锁三行代码简单解决多线程并发写入文件时提示"文件正在由另一进程使用,因此该进程无 ...
- Java高并发情况下的锁机制优化
本文主要讲并行优化的几种方式, 其结构如下: 锁优化 减少锁的持有时间 例如避免给整个方法加锁 1 public synchronized void syncMethod(){ 2 othercode ...
- 【高并发】高并发环境下构建缓存服务需要注意哪些问题?我和阿里P9聊了很久!
写在前面 周末,跟阿里的一个朋友(去年晋升为P9了)聊了很久,聊的内容几乎全是技术,当然了,两个技术男聊得最多的话题当然就是技术了.从基础到架构,从算法到AI,无所不谈.中间又穿插着不少天马行空的想象 ...
- 关于WCF服务在高并发情况下报目标积极拒绝的异常处理
最近弄了个wcf的监控服务,偶尔监控到目标服务会报一个目标积极拒绝的错误.一开始以为服务停止了,上服务器检查目标服务好好的活着.于是开始查原因. 一般来说目标积极拒绝(TCP 10061)的异常主要是 ...
- WCF服务在高并发情况下报目标积极拒绝的异常处理 z
http://www.cnblogs.com/kklldog/p/5037006.html wcf的监控服务,偶尔监控到目标服务会报一个目标积极拒绝的错误.一开始以为服务停止了,上服务器检查目标服务好 ...
- [转]高并发访问下避免对象缓存失效引发Dogpile效应
避免Redis/Memcached缓存失效引发Dogpile效应 Redis/Memcached高并发访问下的缓存失效时可能产生Dogpile效应(Cache Stampede效应). 推荐阅读:高并 ...
随机推荐
- 2018.07.04 POJ 2398 Toy Storage(二分+简单计算几何)
Toy Storage Time Limit: 1000MS Memory Limit: 65536K Description Mom and dad have a problem: their ch ...
- 2018.07.22 洛谷P3047附近的牛(树形dp)
传送门 给出一棵n" role="presentation" style="position: relative;">nn个点的树,每个点上有C ...
- arduino一些内容
arduino 套件使用说明书V1.0.pdf, 步进电机 DHT11 传感器另外一脚要接A0 /* Web client This sketch connects to a website (htt ...
- win10 新增删除文件不刷新
实际上是桌面图标缓存出问题,以下是一个简单动作即可解决问题. 按Win+R键打开“运行”窗口,输入如下命令后按回车键执行: ie4uinit -show 立竿见影,效果同360,魔方等工具软件,可参考 ...
- hB
function Coef = LowPassHb(Fs,Fpass,Apass,n) % -- Fs sample frequency % -- Fpass % -- Apass(dB) % -- ...
- SPSS-非参数检验—两独立样本检验 案例解析
今天跟大家研究和分享一下:spss非参数检验——两独立样本检验, 我还是引用教程里面的案例,以:一种产品有两种不同的工艺生产方法,那他们的使用寿命分别是否相同 下面进行假设:1:一种产品两种不同的工艺 ...
- Last Defence (2014 西安现场赛)
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=94237#problem/K Last Defence Time Limit:3000MS ...
- (树的直径)LightOJ -- 1094
链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=88230#problem/C 求树的直径,这里只不过给每条边增加一个边长属性,变成 ...
- 系统目录APK更新——权限问题
package com.example.wx; import java.io.File;import java.io.FileOutputStream;import java.io.IOExcepti ...
- hdu 3664 Permutation Counting(水DP)
Permutation Counting Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...