Lock及ReentrantReadWriteLock学习

原创 2016年08月29日 14:37:56

参考网上的一个demo,进一步学习了解Java中的Lock使用,demo来自:http://blog.csdn.net/huang_xw/article/details/7090177

废话不多说,直接上代码,注释写的很详细:

package lock;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Lockers 
 * 在多线程编程里面一个重要的概念是锁定,如果一个资源是多个线程共享的,为了保证数据的完整性, 
 * 在进行事务性操作时需要将共享资源锁定,这样可以保证在做事务性操作时只有一个线程能对资源进行操作, 
 * 从而保证数据的完整性。在5.0以前,锁定的功能是由Synchronized关键字来实现的。
 */
public class Lockers {
	
	//内部类
	public static class LockTest{
		Lock lock=new ReentrantLock();
		double value=0d;
		int addtimes=0;
		
		/**
		 * 增加value的值,该方法的操作分为2步,而且相互依赖,必须实现在一个事务中 
         * 所以该方法必须同步,以前的做法是在方法声明中使用Synchronized关键字。 
        */  
		public void addValue(double v){
			lock.lock();//取得锁
			System.out.println("LockTest addValue: "+v+" "+System.currentTimeMillis());
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			this.value+=v;
			this.addtimes++;
			lock.unlock();//释放锁
		}
		
		public double getValue(){
			return this.value;
		}
	}
	
	//相应的测试方法
	public static void testLockTest() throws InterruptedException, ExecutionException{
		final LockTest lockTest=new LockTest();
		//任务1,调用LockTest中的addValue方法
		Runnable taskOne=new Runnable() {
			@Override
			public void run() {
				lockTest.addValue(55.55);
			}
		};
		//任务2,调用LockTest中的getValue方法
		Runnable taskTwo=new Runnable() {
			
			@Override
			public void run() {
				System.out.println("LockTest value:"+lockTest.getValue());
			}
		};
		//新建任务执行服务
		ExecutorService executorService=Executors.newCachedThreadPool();
		Future future=null;
		//同时任务1三次,由于addValue方法使用了锁机制,所以,实质上回顺序执行
		for(int i=0;i<3;i++){
			//submit提交任务并且有返回值
			future=executorService.submit(taskOne);
		}
		//等待最后一个任务1执行完
		future.get();
		//再执行任务2,输出结果
		future=executorService.submit(taskTwo);
		//等待任务2的执行结果
		future.get();
		//关闭服务
		executorService.shutdownNow();
		
	}
	
	
	/**
	 *  ReadWriteLock内置两个Lock,一个是读的Lock,一个是写的Lock。 
     * 多个线程可同时得到读的Lock,但只有一个线程能得到写的Lock, 
     * 而且写的Lock被锁定后,任何线程都不能得到Lock。ReadWriteLock提供的方法有: 
     * readLock(): 返回一个读的lock  
     * writeLock(): 返回一个写的lock, 此lock是排他的。 
     * ReadWriteLockTest很适合处理类似文件的读写操作。 
     * 读的时候可以同时读,但不能写;写的时候既不能同时写也不能读。 
	 */
	public  static class ReadWriteLockTest{
		//定义读写锁
		ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
		
		double value=0d;
		int addtimes=0;
		
		/**
		 * 增加value的值,该方法不允许多个线程同时进入该方法
		 */
		public void addValue(double v){
			//得到writeLock并锁定
			Lock writeLock=lock.writeLock();
			writeLock.lock();
			System.out.println("WriteLock addvalue"+v+" "+System.currentTimeMillis());
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
			try{
				//写工作
				this.value+=v;
				this.addtimes++;
			}finally{
				//释放writeLock
				writeLock.unlock();
			}
		}
		
		/**
		 * 获得信息。当有线程在调用addValue方法时,getInfo得到的信息是不正确的。
		 * 所以也要保证该方法被调用时,没有在调用addValue方法
		 */
		public String getInfo(){
			//得到读锁并锁定
			Lock readLock=lock.readLock();
			readLock.lock();
			System.out.println("ReadLock getInfo"+" "+System.currentTimeMillis());
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
			try{
				//读工作
				return this.value+" "+this.addtimes;
			}finally{
				//释放读锁
				readLock.unlock();
			}
			
		}
	}
	
	//相应的测试方法
	public static void testReadWriteLockTest() throws InterruptedException, ExecutionException{
		final ReadWriteLockTest readWriteLockTest=new ReadWriteLockTest();
		//任务1,调用lockTest的addValue方法
		Runnable taskOne =new Runnable() {
			@Override
			public void run() {
				readWriteLockTest.addValue(55.55);
			}
		};
		//任务2,调用getInfo方法
		Runnable taskTwo=new Runnable() {
			@Override
			public void run() {
				System.out.println("info "+readWriteLockTest.getInfo());
			}
		};
		//新建任务执行服务
		ExecutorService executorService=Executors.newCachedThreadPool();
		Future future=null;
		
		//新建5个任务,前两个是任务1,后2个事任务2
		for(int i=0;i<2;i++){
			future=executorService.submit(taskOne);
		}
		for(int i=0;i<2;i++){
			future=executorService.submit(taskTwo);
		}
		//最后一个任务是任务1
		future=executorService.submit(taskOne);
		// 这5个任务的执行顺序应该是:  
        // 第一个任务1先执行,第二个任务1再执行;这是因为不能同时写,所以必须等。  
        // 然后2个任务2同时执行;这是因为在写的时候,就不能读,所以都等待写结束,  
        // 又因为可以同时读,所以它们同时执行  
        // 最后一个任务1再执行。这是因为在读的时候,也不能写,所以必须等待读结束后,才能写。  
          
		//等待最一个任务2执行完
		future.get();
		//关闭服务
		executorService.shutdownNow();
	}
	
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		Lockers.testLockTest();
		System.out.println("-----------------");
		Lockers.testReadWriteLockTest();
	}

}


版权声明:本文为博主原创文章,未经博主允许不得转载。

ReentrantReadWriteLock详解及应用:缓存和大量数据并发访问

ReentrantReadWriteLock详解:缓存和大量数据并发访问
  • junjle
  • junjle
  • 2017年02月21日 23:34
  • 415

java并发锁ReentrantReadWriteLock读写锁源码分析

本文深入分析了并发锁ReentrantReadWriterLock读写锁的实现原理,由浅到深,从锁的内部数据结构开始分析,讲解了锁的存储原理、锁内部数据组织的优化性能到从源码讲解获取读锁、写锁的步骤,...
  • prestigeding
  • prestigeding
  • 2016年11月22日 15:36
  • 5138

多线程之使用读写锁ReentrantReadWriteLock实现缓存系统

简单地缓存系统:当有线程来取数据时,如果该数据存在我的内存中,我就返回数据;如果不存在我的缓存系统中,那么就去查数据库,返回数据的同时保存在我的缓存中。 其中涉及到读写问题:当多个线程执行读操作时(...
  • fengshizty
  • fengshizty
  • 2014年11月09日 10:02
  • 1743

java 中 ReentrantReadWriteLock的读锁和写锁的使用

jdk文档中关于ReentrantReadWriteLock类使用的一个很好的例子,以下是具体的介绍:    在使用某些种类的 Collection 时,可以使用 ReentrantReadWri...
  • Erica_1230
  • Erica_1230
  • 2015年01月17日 14:54
  • 1878

java多线程:ReentrantReadWriteLock读写锁的使用

读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可。如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;如果你的代码修改数据,只能有一...
  • u014078192
  • u014078192
  • 2014年06月11日 10:40
  • 1516

Android并发编程之如何使用ReentrantReadWriteLock替代synchronized来提高程序的效率

Java的synchronized关键字可以帮助我们解决多线程并发的问题,比如我们有一个公共资源,多个线程都来操作这个公共的资源,就会出现并发的问题,比如不同的线程对同一个数据同时进行读和写,肯定会使...
  • nugongahou110
  • nugongahou110
  • 2015年12月16日 14:46
  • 1723

深入理解读写锁—ReadWriteLock源码分析

ReadWriteLock管理一组锁,一个是只读的锁,一个是写锁。读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的。 所有读写锁的实现必须确保写操作对读操作的内存影响。换句话说,一个获得了读...
  • qq_19431333
  • qq_19431333
  • 2017年04月24日 09:00
  • 4117

ReentrantReadWriteLock可重入读写锁使用

特点可重入:就是同一个线程可以重复加锁,可以对同一个锁加多次,每次释放的时候回释放一次,直到该线程加锁次数为0,这个线程才释放锁。比如同一个线程中可以对同一个锁加多次写入锁。写线程获取写入锁后可以再次...
  • heqiangflytosky
  • heqiangflytosky
  • 2015年11月13日 11:38
  • 947

聊聊高并发(二十八)解析java.util.concurrent各个组件(十) 理解ReentrantReadWriteLock可重入读-写锁

这篇讲讲ReentrantReadWriteLock可重入读写锁,它不仅是读写锁的实现,并且支持可重入性。...
  • ITer_ZC
  • ITer_ZC
  • 2014年11月11日 17:37
  • 3253

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

最近在研究jdk的锁机制,reentrantreadwritelock实现了读写锁分离机制,其中读锁可以被多个线程重入,写锁是独占的,并且在写锁开启的时候,读取操作进入阻塞队列。这里我做了一个测试,来...
  • a4613934
  • a4613934
  • 2016年06月14日 14:31
  • 480
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Lock及ReentrantReadWriteLock学习
举报原因:
原因补充:

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