`
hanhan8020
  • 浏览: 44591 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

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. }  
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author: yanxuxin
 * @date: 2010-1-7
 */
public class ReentrantReadWriteLockSample {

	public static void main(String[] args) {
		testReadLock();
//		testWriteLock();
	}
	
	public static void testReadLock() {
	   final ReadWriteLockSampleSupport support = new ReadWriteLockSampleSupport();
		support.initCache();
		
		Runnable runnable = new Runnable() {
			public void run() {
				support.get("test");
			}
		};
		
		new Thread(runnable).start();
		new Thread(runnable).start();
		
		new Thread(new Runnable() {
			public void run() {
				support.put("test", "test");
			}
		}).start();
	}
	
	public static void testWriteLock() {
	   final ReadWriteLockSampleSupport support = new ReadWriteLockSampleSupport();
		support.initCache();
		
		new Thread(new Runnable() {
			public void run() {
				support.put("key1", "value1");
			}
		}).start();
		
		new Thread(new Runnable() {
			public void run() {
				support.put("key2", "value2");
			}
		}).start();
		
		new Thread(new Runnable() {
			public void run() {
				support.get("key1");
			}
		}).start();
	}
}

class ReadWriteLockSampleSupport {
	private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	private final Lock readLock = lock.readLock();
	private final Lock writeLock = lock.writeLock();
	
	private volatile  boolean completed;
	private Map<String,String> cache;
	
	public void initCache() {
		readLock.lock();
		if(!completed) {
			// Must release read lock before acquiring write lock
			readLock.unlock(); // (1)
			writeLock.lock();  // (2)
			if(!completed) {
				cache = new HashMap<String,String>(32);
				completed = true;
			}
			// Downgrade by acquiring read lock before releasing write lock
			readLock.lock();    // (3)
			writeLock.unlock(); // (4) Unlock write, still hold read
		}
		
		System.out.println("empty? " + cache.isEmpty());
		readLock.unlock();
	}
	
	public String get(String key) {
		readLock.lock();
		System.out.println(Thread.currentThread().getName() + " read.");
		startTheCountdown();
		try{
			return cache.get(key);
		}
		finally{
			readLock.unlock();
		}
	}
	
	public String put(String key, String value) {
		writeLock.lock();
		System.out.println(Thread.currentThread().getName() + " write.");
		startTheCountdown();
		try{
			return cache.put(key, value);
		}
		finally {
			writeLock.unlock();
		}
	}
	
	/**
	 * A simple countdown,it will stop after about 5s. 
	 */
	public void startTheCountdown() {
		long currentTime = System.currentTimeMillis();
		for(;;) {
			long diff = System.currentTimeMillis() - currentTime;
			if(diff > 5000) {
				break;
			}
		}
	}
}


    这个例子改造自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前端,不管是移动设备的三方开发还是专业的视频剪辑技术,我都希望很自然的感兴趣了,有条件了就去狠狠的玩玩。我想我迷恋的只是高性能的计算机和互联网,哈哈

分享到:
评论

相关推荐

    8、读写锁ReentrantReadWriteLock&StampLock详解.pdf

    6.JUC并发工具类在大厂的应用场景详解 (1).pdf 7、深入理解 AQS 独占锁之 Reentrantlock 源码分析 (1).pdf 8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10...

    6、JUC并发工具类在大厂的应用场景详解(1).pdf

    6.JUC并发工具类在大厂的应用场景详解 (1).pdf 7、深入理解 AQS 独占锁之 Reentrantlock 源码分析 (1).pdf 8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10...

    counter:计算端点发生热点的次数

    使用ReentrantReadWriteLock在应用程序中实现线程安全 终点 POST / chargingSessions-添加新的充电会话 PUT / chargingSessions / {id}-更新现有的充电会话 GET / chargingSessions-检索所有充电会话 GET / ...

    encrypt-N-upload:该项目展示了从AES到Java的AES加密解密,带有测试用例和ReentrantReadWriteLock示例用法的Spring MVC多部分文件上传

    encrypt-N-upload是一个演示应用程序,它最初是一个集成应用程序,可以将身份验证请求从内部服务器代理到外部授权服务。 该应用程序还接受文件上传,然后将其转发到外部服务。 原始形式的应用程序非常具体,任何人...

    7、深入理解AQS独占锁之ReentrantLock源码分析(1).pdf

    6.JUC并发工具类在大厂的应用场景详解 (1).pdf 7、深入理解 AQS 独占锁之 Reentrantlock 源码分析 (1).pdf 8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10...

    10、阻塞队列BlockingQueue实战及其原理分析.pdf

    6.JUC并发工具类在大厂的应用场景详解 (1).pdf 7、深入理解 AQS 独占锁之 Reentrantlock 源码分析 (1).pdf 8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10...

    9、并发容器(Map、List、Set)实战及其原理.pdf

    6.JUC并发工具类在大厂的应用场景详解 (1).pdf 7、深入理解 AQS 独占锁之 Reentrantlock 源码分析 (1).pdf 8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10...

    Java并发编程原理与实战

    线程之间通信之join应用与实现原理剖析.mp4 ThreadLocal 使用及实现原理.mp4 并发工具类CountDownLatch详解.mp4 并发工具类CyclicBarrier 详解.mp4 并发工具类Semaphore详解.mp4 并发工具类Exchanger详解.mp4 ...

    Java并发包源码分析(JDK1.8)

    Java并发包源码分析(JDK1.8):囊括了java.util.concurrent包中大部分类的源码分析,其中涉及automic包,locks包(AbstractQueuedSynchronizer、ReentrantLock、ReentrantReadWriteLock、LockSupport等),queue...

    龙果 java并发编程原理实战

    第35节线程之间通信之join应用与实现原理剖析00:10:17分钟 | 第36节ThreadLocal 使用及实现原理00:17:41分钟 | 第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52...

    Java 并发编程原理与实战视频

    第35节线程之间通信之join应用与实现原理剖析00:10:17分钟 | 第36节ThreadLocal 使用及实现原理00:17:41分钟 | 第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52...

    龙果java并发编程完整视频

    第35节线程之间通信之join应用与实现原理剖析00:10:17分钟 | 第36节ThreadLocal 使用及实现原理00:17:41分钟 | 第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52...

    java并发编程

    第35节线程之间通信之join应用与实现原理剖析00:10:17分钟 | 第36节ThreadLocal 使用及实现原理00:17:41分钟 | 第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52...

    Java并发编程实战

    14.6.4 ReentrantReadWriteLock259 第15章 原子变量与非阻塞同步机制261 15.1 锁的劣势261 15.2 硬件对并发的支持262 15.2.1 比较并交换263 15.2.2 非阻塞的计数器264 15.2.3 JVM对CAS的支持265 15.3 原子...

    javaSE代码实例

    17.3.3 ReadWriteLock接口与ReentrantReadWriteLock类简介 390 17.3.4 ReentrantReadWriteLock读/写锁的具体使用 391 17.4 信号量的使用 393 17.4.1 Semaphore类简介 393 17.4.2 Semaphore类的具体使用 ...

    课程实验基于Java实现的分布式存储系统源码+项目说明.tar

    * 使用 **ReenTrantReadWriteLock** 降低同一文件读写冲突,提高文件IO并发度 ### 模块说明: **Client:** 与应用直接交互的服务,提供文件操作相关接口 **Meta:** 维持文件元数据,统一管理chunk信息 **chunk-...

    汪文君高并发编程实战视频资源全集

    ReentrantReadWriteLock详细讲解_.mp4  高并发编程第三阶段28讲 Condition初步使用,提出几个疑问_.mp4  高并发编程第三阶段29讲 关于Condition疑问的几个小实验,对比Wait&amp;Notify_.mp4  高并发编程第三阶段...

    汪文君高并发编程实战视频资源下载.txt

    ReentrantReadWriteLock详细讲解_.mp4  高并发编程第三阶段28讲 Condition初步使用,提出几个疑问_.mp4  高并发编程第三阶段29讲 关于Condition疑问的几个小实验,对比Wait&amp;Notify_.mp4  高并发编程第三阶段...

Global site tag (gtag.js) - Google Analytics