读写锁

转载 2012年03月22日 11:09:55

ReentrantReadWriteLock

 说到ReentrantReadWriteLock,首先要做的是与ReentrantLock划清界限。它和后者都是单独的实现,彼此之间没有继承或实现的关系。然后就是总结这个锁机制的特性了: 

     (a).重入方面其内部的WriteLock可以获取ReadLock,但是反过来ReadLock想要获得WriteLock则永远都不要想。 

     (b).WriteLock可以降级为ReadLock,顺序是:先获得WriteLock再获得ReadLock,然后释放WriteLock,这时候线程将保持Readlock的持有。反过来ReadLock想要升级为WriteLock则不可能,为什么?参看(a),呵呵. 

     (c).ReadLock可以被多个线程持有并且在作用时排斥任何的WriteLock,而WriteLock则是完全的互斥。这一特性最为重要,因为对于高读取频率而相对较低写入的数据结构,使用此类锁同步机制则可以提高并发量。 

     (d).不管是ReadLock还是WriteLock都支持Interrupt,语义与ReentrantLock一致。 

     (e).WriteLock支持Condition并且与ReentrantLock语义一致,而ReadLock则不能使用Condition,否则抛出UnsupportedOperationException异常。 

      以上就是比较重要的,或者衡量是否使用ReentrantReadWriteLock的基础了。下面还是写个小例子说明部分内容: 
Java代码  收藏代码
  1. import java.util.HashMap;  
  2. import java.util.Map;  
  3. import java.util.concurrent.locks.Lock;  
  4. import java.util.concurrent.locks.ReentrantReadWriteLock;  
  5.   
  6. /** 
  7.  * @author: yanxuxin 
  8.  * @date: 2010-1-7 
  9.  */  
  10. public class ReentrantReadWriteLockSample {  
  11.   
  12.     public static void main(String[] args) {  
  13.         testReadLock();  
  14. //      testWriteLock();  
  15.     }  
  16.       
  17.     public static void testReadLock() {  
  18.        final ReadWriteLockSampleSupport support = new ReadWriteLockSampleSupport();  
  19.         support.initCache();  
  20.           
  21.         Runnable runnable = new Runnable() {  
  22.             public void run() {  
  23.                 support.get("test");  
  24.             }  
  25.         };  
  26.           
  27.         new Thread(runnable).start();  
  28.         new Thread(runnable).start();  
  29.           
  30.         new Thread(new Runnable() {  
  31.             public void run() {  
  32.                 support.put("test""test");  
  33.             }  
  34.         }).start();  
  35.     }  
  36.       
  37.     public static void testWriteLock() {  
  38.        final ReadWriteLockSampleSupport support = new ReadWriteLockSampleSupport();  
  39.         support.initCache();  
  40.           
  41.         new Thread(new Runnable() {  
  42.             public void run() {  
  43.                 support.put("key1""value1");  
  44.             }  
  45.         }).start();  
  46.           
  47.         new Thread(new Runnable() {  
  48.             public void run() {  
  49.                 support.put("key2""value2");  
  50.             }  
  51.         }).start();  
  52.           
  53.         new Thread(new Runnable() {  
  54.             public void run() {  
  55.                 support.get("key1");  
  56.             }  
  57.         }).start();  
  58.     }  
  59. }  
  60.   
  61. class ReadWriteLockSampleSupport {  
  62.     private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();  
  63.     private final Lock readLock = lock.readLock();  
  64.     private final Lock writeLock = lock.writeLock();  
  65.       
  66.     private volatile  boolean completed;  
  67.     private Map<String,String> cache;  
  68.       
  69.     public void initCache() {  
  70.         readLock.lock();  
  71.         if(!completed) {  
  72.             // Must release read lock before acquiring write lock  
  73.             readLock.unlock(); // (1)  
  74.             writeLock.lock();  // (2)  
  75.             if(!completed) {  
  76.                 cache = new HashMap<String,String>(32);  
  77.                 completed = true;  
  78.             }  
  79.             // Downgrade by acquiring read lock before releasing write lock  
  80.             readLock.lock();    // (3)  
  81.             writeLock.unlock(); // (4) Unlock write, still hold read  
  82.         }  
  83.           
  84.         System.out.println("empty? " + cache.isEmpty());  
  85.         readLock.unlock();  
  86.     }  
  87.       
  88.     public String get(String key) {  
  89.         readLock.lock();  
  90.         System.out.println(Thread.currentThread().getName() + " read.");  
  91.         startTheCountdown();  
  92.         try{  
  93.             return cache.get(key);  
  94.         }  
  95.         finally{  
  96.             readLock.unlock();  
  97.         }  
  98.     }  
  99.       
  100.     public String put(String key, String value) {  
  101.         writeLock.lock();  
  102.         System.out.println(Thread.currentThread().getName() + " write.");  
  103.         startTheCountdown();  
  104.         try{  
  105.             return cache.put(key, value);  
  106.         }  
  107.         finally {  
  108.             writeLock.unlock();  
  109.         }  
  110.     }  
  111.       
  112.     /** 
  113.      * A simple countdown,it will stop after about 5s.  
  114.      */  
  115.     public void startTheCountdown() {  
  116.         long currentTime = System.currentTimeMillis();  
  117.         for(;;) {  
  118.             long diff = System.currentTimeMillis() - currentTime;  
  119.             if(diff > 5000) {  
  120.                 break;  
  121.             }  
  122.         }  
  123.     }  
  124. }  

    这个例子改造自JDK的API提供的示例,其中ReadWriteLockSampleSupport辅助类负责维护一个Map,当然前提是这个Map大部分的多线程下都是读取,只有很少的比例是多线程竞争修改Map的值。其中的initCache()简单的说明了特性(a),(b).在这个方法中如果把注释(1)和(2)处的代码调换位置,就会发现轻而易举的死锁了,当然是因为特性(1)的作用了。而注释(3),(4)处的代码位置则再次证明了特性(a),并且有力的反映了特性(b)--WriteLock在cache初始化完毕之后,降级为ReadLock。另外get(),put()方法在线程获取锁之后会在方法中呆上近5s的时间。 

     ReentrantReadWriteLockSample中的两个静态测试方法则分别测试了ReadLock和WriteLock的排斥性。testReadLock()中,开启三个线程,前两者试图获取ReadLock而后者去获取WriteLock。执行结果可以看到:ReadWriteLockSampleSupport的get()方法中的打印结果在前两个线程中几乎同时显示,而put()中的打印结果则要等上近5s。这就说明了,ReadLock可以多线程持有并且排斥WriteLock的持有线程。testWriteLock()中,也开启三个线程。前两个是去获取WriteLock,最后一个获取ReadLock。执行的结果是三个打印结果都有近5s的间隔时间,这说明了WriteLock是独占的,比较独! 

    这篇ReentrantReadWriteLock的总结写的有点迟了,主要是最近对js和ajax很有兴趣,突然觉得css也很好玩。看着网上很多人对技术的狂热和个人规划,我想对我而言:不迷恋技术而是作为兴趣,不管是J2EE还是Web前端,不管是移动设备的三方开发还是专业的视频剪辑技术,我都希望很自然的感兴趣了,有条件了就去狠狠的玩玩。我想我迷恋的只是高性能的计算机和互联网,哈哈。

相关文章推荐

读写锁,不支持重入

  • 2014-02-20 13:54
  • 512KB
  • 下载

读写锁实现例子

  • 2014-08-14 13:11
  • 76KB
  • 下载

ReentrantReadWriteLock重入锁中的读写锁在公平和非公平模式下的资源抢占测验

最近在研究jdk的锁机制,reentrantreadwritelock实现了读写锁分离机制,其中读锁可以被多个线程重入,写锁是独占的,并且在写锁开启的时候,读取操作进入阻塞队列。这里我做了一个测试,来...

C++ 读写锁

线程读写锁

//读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可。 //如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁; //如果你的代...

net并发数据结构读写锁

  • 2013-11-26 15:34
  • 32KB
  • 下载

windows读写锁

秒杀多线程第十四篇 读者写者问题继 读写锁SRWLock

在《秒杀多线程第十一篇读者写者问题》文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题。问题虽然得到了解决,但代码有点复杂。本篇将介绍一种新方法——读写锁SRWLock来解决这一问题。读写锁...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)