• 读/写锁的实现和应用(高并发状态下的map实现)


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

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

    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<Thread, Integer> readingThreads =
    
         new HashMap<Thread, Integer>();
    
    
    
     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<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(); }
        }
     }
  • 相关阅读:
    js中调用ocx控件
    web.xml配置文件中<async-supported>true</async-supported>报错的解决方案
    shiro整合spring配置
    shiro中的reaml理解及实现机制
    oracle数据库安装
    关于身份认证、角色认证和权限认证的shiro-web例子
    创建maven管理的web项目
    hadoop Hive 的建表 和导入导出及索引视图
    hadoop Mapreduce组件介绍
    hadoop hive组件介绍及常用cli命令
  • 原文地址:https://www.cnblogs.com/starcrm/p/4996910.html
Copyright © 2020-2023  润新知