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

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

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实现)的更多相关文章

  1. php高并发状态下文件的读写

    php高并发状态下文件的读写   背景 1.对于PV不高或者说并发数不是很大的应用,不用考虑这些,一般的文件操作方法完全没有问题 2.如果并发高,在我们对文件进行读写操作时,很有可能多个进程对进一文件 ...

  2. C++高并发场景下读多写少的解决方案

    C++高并发场景下读多写少的解决方案 概述 一谈到高并发的解决方案,往往能想到模块水平拆分.数据库读写分离.分库分表,加缓存.加mq等,这些都是从系统架构上解决.单模块作为系统的组成单元,其性能好坏也 ...

  3. C++高并发场景下读多写少的优化方案

    概述 一谈到高并发的优化方案,往往能想到模块水平拆分.数据库读写分离.分库分表,加缓存.加mq等,这些都是从系统架构上解决.单模块作为系统的组成单元,其性能好坏也能很大的影响整体性能,本文从单模块下读 ...

  4. C# 防止同时调用=========使用读写锁三行代码简单解决多线程并发的问题

    http://www.jb51.net/article/99718.htm     本文主要介绍了C#使用读写锁三行代码简单解决多线程并发写入文件时提示"文件正在由另一进程使用,因此该进程无 ...

  5. Java高并发情况下的锁机制优化

    本文主要讲并行优化的几种方式, 其结构如下: 锁优化 减少锁的持有时间 例如避免给整个方法加锁 1 public synchronized void syncMethod(){ 2 othercode ...

  6. 【高并发】高并发环境下构建缓存服务需要注意哪些问题?我和阿里P9聊了很久!

    写在前面 周末,跟阿里的一个朋友(去年晋升为P9了)聊了很久,聊的内容几乎全是技术,当然了,两个技术男聊得最多的话题当然就是技术了.从基础到架构,从算法到AI,无所不谈.中间又穿插着不少天马行空的想象 ...

  7. 关于WCF服务在高并发情况下报目标积极拒绝的异常处理

    最近弄了个wcf的监控服务,偶尔监控到目标服务会报一个目标积极拒绝的错误.一开始以为服务停止了,上服务器检查目标服务好好的活着.于是开始查原因. 一般来说目标积极拒绝(TCP 10061)的异常主要是 ...

  8. WCF服务在高并发情况下报目标积极拒绝的异常处理 z

    http://www.cnblogs.com/kklldog/p/5037006.html wcf的监控服务,偶尔监控到目标服务会报一个目标积极拒绝的错误.一开始以为服务停止了,上服务器检查目标服务好 ...

  9. [转]高并发访问下避免对象缓存失效引发Dogpile效应

    避免Redis/Memcached缓存失效引发Dogpile效应 Redis/Memcached高并发访问下的缓存失效时可能产生Dogpile效应(Cache Stampede效应). 推荐阅读:高并 ...

随机推荐

  1. Windows Server 2012如何实现双网卡绑定

    在windows server 2012 之前我们在服务器上如果要实现双网卡绑定则需要向服务器厂家所要相应的软件,但是现在强大的windows server 2012的到来使我们省去了所有的麻烦,因为 ...

  2. Python特殊方法

    # __slots__如果要限制添加的属性,例如,Student类只允许添加 name.gender和score 这3个属性,就可以利用Python的一个特殊的__slots__来实现. # __sl ...

  3. CentOS yum 源的配置与使用(引用)

    http://www.cnblogs.com/mchina/archive/2013/01/04/2842275.html

  4. Java基础知识学习笔记(一)

    理解面向对象: Java纯粹的面向对象的程序设计语言,主要表现为Java完全支持面向对象的三个基本特征:继承.封装.多态. Java程序的最小单位是类,类代表客观世界中具有某种特征的一类事物,这些类可 ...

  5. 超全table功能Datatables使用的填坑之旅--2:post 动态传参: 解决: ajax 传参无值问题.

    官网解释与方法:1 当向服务器发出一个ajax请求,Datatables将会把服务器请求到的数据构造成一个数据对象. 2 实际上他是参考jQuery的ajax.data属性来的,他能添加额外的参数传给 ...

  6. java thrift返回List异常

    对于下段代码: public List<String> hmget(String key, List<String> fields) throws org.apache.thr ...

  7. C++中的结构体的认识

    C++中的结构体的认识 1. typedef的用法 在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分,但它并不实际分配内存空间. 实例像:typedef ...

  8. hdu 2153 仙人球的残影

    题目 这道题可以有两种写法: 第一种:找规律,如下: #include <stdio.h> int main() { int n,i,j,res; while (scanf("% ...

  9. handsontable 问题

    碰到问题了,去官网上找community:http://docs.handsontable.com/0.16.1/tutorial-quick-start.html 1. 描述:把handson ta ...

  10. 深入研究java.lang.Process类

    一.概述 Process类是一个抽象类(所有的方法均是抽象的),封装了一个进程(即一个执行程序).       Process 类提供了执行从进程输入.执行输出到进程.等待进程完成.检查进程的退出状态 ...