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

分享到:
评论

相关推荐

    ReadWriteLock接口及其实现ReentrantReadWriteLock方法

    其次,ReentrantReadWriteLock 可以提供公平锁和非公平锁两种锁类型,满足不同的应用场景。最后,ReentrantReadWriteLock 的实现方式简单、灵活,易于维护和扩展。 ReadWriteLock 接口及其实现 ...

    深入浅出ReentrantReadWriteLock源码解析.docx

    【深入浅出ReentrantReadWriteLock源码解析】 ReentrantReadWriteLock是Java并发包中的一个核心类,它提供...通过深入研究源码,我们可以更好地掌握并发控制的策略,以及如何在实际项目中应用这些策略来优化代码性能。

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

    根据提供的文件信息,本文将详细解析读写锁`ReentrantReadWriteLock`以及`StampLock`在Java并发编程中的应用场景及其实现原理。 ### 一、读写锁介绍 #### 1.1 读写锁的基本概念 读写锁是一种特殊的锁机制,它可以...

    Java 多线程与并发(12-26)-JUC锁- ReentrantReadWriteLock详解.pdf

    然而,实际应用中,超过这个数值可能会导致溢出问题,因此通常需要避免过高的重入次数。 4. **ThreadLocalHoldCounter和HoldCounter的作用** - HoldCounter是一个内部类,用于存储线程的读锁重入次数。 - ...

    Java分布式应用学习笔记06浅谈并发加锁机制分析

    总结来说,Java中的并发加锁机制非常灵活且强大,通过对`ReentrantLock`和`ReentrantReadWriteLock`等工具的理解和应用,可以有效地解决多线程环境下的并发控制问题。希望本文能帮助读者更好地理解和掌握Java并发...

    contention-profiling:ReentrantLock 和 ReentrantReadWriteLock 上的配置文件争用

    在Java编程语言中,线程安全是多线程应用程序中至关重要的一个方面。`ReentrantLock`和`ReentrantReadWriteLock`是Java并发包`java.util.concurrent.locks`中的两个重要工具,它们提供了比标准`synchronized`关键字...

    性能调优指南--计算机系统Java应用程序(不断完善)代码示例

    6. **锁优化**:使用轻量级锁(如synchronized关键字)、读写锁(java.util.concurrent.locks.ReentrantReadWriteLock)或并发集合(如ConcurrentHashMap)来减少锁竞争。 7. **延迟加载(Lazy Initialization)**...

    Java的两种读写锁介绍

    本文将深入探讨Java中的两种读写锁:ReentrantReadWriteLock和StampedLock,并分析它们的工作原理、特点以及如何在实际开发中进行应用。 一、ReentrantReadWriteLock(可重入读写锁) 1. **简介**: ...

    reader and writer

    ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); ReadLock readLock = lock.readLock(); WriteLock writeLock = lock.writeLock(); ``` 2. **读者部分**:当一个线程想要读取数据时,它需要获取读锁...

    Mybatis-plus基于redis实现二级缓存过程解析

    然而,在高并发、高性能的应用场景中,数据库的查询操作可能会成为性能瓶颈。为了解决这个问题,Mybatis-plus提供了基于Redis的二级缓存机制,能够大幅度提高应用程序的性能。 在Mybatis-plus中,二级缓存是指在...

    读者写者公平操作

    在计算机科学和操作系统领域,"读者写者公平操作"是一个经典的多线程...理解和熟练应用这一机制对于开发高并发的Java应用程序至关重要。在实际项目中,根据具体需求选择公平或非公平策略,以达到性能和公平性的平衡。

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

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

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

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

    java 读写锁代码

    在Java的`java.util.concurrent.locks`包中,`ReentrantReadWriteLock`类实现了读写锁的功能。这个锁允许多个读取者同时访问资源,但在有写入者时,所有读取者和写入者都会被阻塞,以确保数据的一致性。下面我们将...

    读写线程模仿

    这种场景在图形化用户界面(GUI)应用中尤为常见,因为用户交互通常会触发数据的读取或写入操作。 在Java中,实现读写线程的同步通常有两种策略:互斥访问和读者-写者问题。"读者优先"的策略是一种解决读者-写者...

    浅谈多线程中的锁的几种用法总结(必看)

    在实际应用中,ReentrantLock 和 ReentrantReadWriteLock 都可以用于解决多线程之间的资源竞争问题,但是 ReentrantReadWriteLock 可以提供更高的并发度。在选择锁机制时,需要根据实际情况选择合适的锁机制。 锁...

    homework-ReadWriteLock-KristampsW-main.zip

    - 数据库连接池、缓存系统等都是读写锁的经典应用场景。 6. **最佳实践**: - 获取锁时应尽可能选择读锁,除非需要修改共享资源。 - 使用完锁后,记得及时释放,避免死锁的发生。 - 注意锁的公平性和非公平性...

    读写锁_读写锁_

    读写锁是多线程编程中的一个重要概念,用于提高并发访问数据时的效率。在并发环境中,如果多个线程同时读取数据,...通过深入理解读写锁的工作原理,并在实际项目中谨慎应用,我们可以构建出更加高效、可靠的并发程序。

    java多线程经典案例

    Java提供了多种同步机制,如synchronized关键字、Lock接口(ReentrantLock、ReentrantReadWriteLock)以及Semaphore信号量。synchronized用于方法或代码块,可以保证同一时间只有一个线程执行特定代码,避免数据冲突...

    北京圣思园科技有限公司JAVA面授培训大纲

    - **并发包详解**:深入分析ConcurrentHashMap、ThreadPoolExecutor、FutureTask、Semaphore、Condition、ReentrantReadWriteLock等类和接口的核心源代码。 - **JVM锁与并发机制**:对比JDK 1.4锁与JDK 5.0并发包的...

Global site tag (gtag.js) - Google Analytics