读/写锁的实现和应用(高并发状态下的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(); }
}
}
上一篇:[Go] 使用读写锁对map资源进行安全处理


下一篇:vb- ----之常用函数