读/写锁的实现和应用(高并发状态下的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(); }
    }
 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值