Lock及ReentrantReadWriteLock学习

参考网上的一个demo,进一步学习了解Java中的Lock使用,demo来自:http://blog.youkuaiyun.com/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();
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值