博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
读/写锁的实现和应用(高并发状态下的map实现)
阅读量:4135 次
发布时间:2019-05-25

本文共 4631 字,大约阅读时间需要 15 分钟。

程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写(译者注:也就是说:读-读能共存,读-写不能共存,写-写不能共存)。这就需要一个读/写锁来解决这个问题。

按照上面的叙述,简单的实现出一个读/写锁

public class ReadWriteLock{  private int readers = 0;  private int writers = 0;  private int writeRequests = 0;  public synchronized void lockRead()      throws InterruptedException{      while(writers > 0 || writeRequests > 0){          wait();      }      readers++;  }  public synchronized void unlockRead(){      readers--;      notifyAll();  }  public synchronized void lockWrite()      throws InterruptedException{      writeRequests++;      while(readers > 0 || writers > 0){          wait();      }      writeRequests--;      writers++;  }  public synchronized void unlockWrite()      throws InterruptedException{      writers--;      notifyAll();  }}

 

 

ReadWriteLock类中,读锁和写锁各有一个获取锁和释放锁的方法。

 

可重入的ReadWriteLock的完整实现

下面是完整的ReadWriteLock实现。为了便于代码的阅读与理解,简单对上面的代码做了重构。重构后的代码如下。

public class ReadWriteLock{ private Map
readingThreads = new HashMap
(); private int writeAccesses = 0; private int writeRequests = 0; private Thread writingThread = null; public synchronized void lockRead() throws InterruptedException{ Thread callingThread = Thread.currentThread(); while(! canGrantReadAccess(callingThread)){ wait(); } readingThreads.put(callingThread, (getReadAccessCount(callingThread) + 1)); } 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 == 1){ readingThreads.remove(callingThread); } else { readingThreads.put(callingThread, (accessCount -1)); } 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 == 0){ 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 0; return accessCount.intValue(); } private boolean hasReaders(){ return readingThreads.size() > 0; } private boolean isReader(Thread callingThread){ return readingThreads.get(callingThread) != null; } private boolean isOnlyReader(Thread callingThread){ return readingThreads.size() == 1 && readingThreads.get(callingThread) != null; } private boolean hasWriter(){ return writingThread != null; } private boolean isWriter(Thread callingThread){ return writingThread == callingThread; } private boolean hasWriteRequests(){ return this.writeRequests > 0; }}

应用:线程安全并且高并发状态下的map实现

class RWDictionary {    private final Map
m = new TreeMap
(); 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(); } } }

 

转载地址:http://rtpvi.baihongyu.com/

你可能感兴趣的文章
Codeforces Global Round 4(ABCDE)
查看>>
subsequence 1(牛客多校第五场记忆化搜索+组合数学)
查看>>
Welfare State CodeForces - 1199D(线段树)
查看>>
linux下touch的运用以及在linux下创建可运行的.sh文件
查看>>
json和jsonp的使用格式
查看>>
Oracle密码过期,取消密码180天限制
查看>>
Linux下磁盘分区,格式化以及挂载
查看>>
Oracle创建用户并给用户授权查询指定表或视图的权限
查看>>
Linux下Oracle数据库自动备份Shell脚本
查看>>
Linux下oracle定时备份教程
查看>>
ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var mysql 启动不了
查看>>
Oracle报错,ORA-28001: 口令已经失效
查看>>
解决linux根目录磁盘空间满
查看>>
mysql报错ERROR 1054(42S22) Unknown column 'password' in ‘field list’
查看>>
nginx 负载均衡管理的项目均不能正常运行的原因
查看>>
MYSQL主从
查看>>
Linux下安装mysql5.7
查看>>
Linux下如何调整根目录的空间大小
查看>>
Navicat连接MySQL时报错1142
查看>>
linux telnet命令
查看>>