读/写锁的实现和应用(高并发状态下的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效应). 推荐阅读:高并 ...
随机推荐
- 《沉静领导》读书笔记zz
就 像作者说的,这本书“只是一篇简单的随笔,它描绘并阐明了一种关于领导之道的思考方式,并且为把这种思考方式应用到实际行动中提供了指南.”但是,仔细想 来,倒有一点不同见解,或许,它描述的不可以叫做“领 ...
- 情境领导II
情境领导理论认为,领导者的行为要与被领导者的准备程度相适应,才能取得有效的领导效果,也就是说领导风格不是一成不变的,而要根据环境及员工的变化而改变. 三大技巧分别为诊断.弹性与约定领导型态.诊断是评估 ...
- 2018.09.23 bzoj1076: [SCOI2008]奖励关(期望+状压dp)
传送门 一道神奇的期望状压dp. 用f[i][j]f[i][j]f[i][j]表示目前在第i轮已选取物品状态为j,从现在到第k轮能得到的最大贡献. 如果我们从前向后推有可能会遇到不合法的情况. 所以我 ...
- 2018.09.19 atcoder Snuke's Coloring(思维题)
传送门 谁能想到这道题会写这么久. 本来是一道很sb的题啊. 就是每次选一个点只会影响到周围的九个方格,随便1e9进制就可以hash了,但是我非要作死用stl写. 结果由于技术不够高超,一直调不出来. ...
- 2018.09.16 loj#10241. 取石子游戏 1(博弈论)
传送门 好像是某年的初赛题啊. 有个很显然的结论. 当n" role="presentation" style="position: relative;&quo ...
- 2018.07.27 bzoj3064: Tyvj 1518 CPU监控(线段树)
传送门 线段树好题. 维护区间加,区间覆盖,区间最大,区间历史最大. 这个东西在国家集训队2016论文集之<区间最值操作与历史最值问题--杭州学军中学 吉如一>中讲的已经很详细了. 简单来 ...
- 2018.07.22 bzoj3613: [Heoi2014]南园满地堆轻絮(逆序对结论题)
传送门 做这道题有一个显然的结论,就是要使这个数列单调不减,就要使所有逆序对保证单调不减,也就是求出所有逆序对的最大差值,然后除以2然后就没了. 代码如下: #include<bits/stdc ...
- Django(3)
https://www.cnblogs.com/yuanchenqi/articles/7429279.html
- mysql date_sub用法
查询一天: select * from table where to_days(column_time) = to_days(now()); select * from table where dat ...
- 静态代码块和this
/* 静态代码块.随着类的加载而执行.而且只执行一次. 作用: 用于给类进行初始化. */class StaticCode{ static int num ; static { num = 10;// ...