标签:
摘要:本文主要讲了读写锁。
一、读写锁ReadWriteLock
在上文中回顾了并发包中的可重入锁ReentrantLock,并且也分析了它的源码。从中我们知道它是一个单一锁(笔者自创概念),意思是在多人读、多人写、或同时有人读和写时。只能有一个人能拿到锁,执行代码。但是在很多场景。我们想控制它能多人同时读,但是又不让它多人写或同时读和写时。(想想这是不是和数据库的可重复读有点类型?),这时就可以使用读写锁:ReadWriteLock。
下面来看一个应用
package com.lin;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockTest {
	
   public  static  void main(String[] args) {
	   //创建一个锁对象 ,非公平锁
       ReadWriteLock lock = new ReentrantReadWriteLock(false);  
       //创建一个线程池  
       ExecutorService pool = Executors.newCachedThreadPool(); 
	   //设置一个账号,设置初始金额为10000
       Account account = new Account(lock,"123456",10000);
        
       //账号取钱10次,存钱10次,查询20次
       for(int i=1;i<=10;i++) {
    	   Operation operation1 = new Operation(account,"take");
    	   Operation operation2 = new Operation(account,"query");
    	   Operation operation3 = new Operation(account,"save");
    	   Operation operation4 = new Operation(account,"query");
    	   pool.execute(operation1);
    	   pool.execute(operation2);
    	   pool.execute(operation3);
    	   pool.execute(operation4);
       }
       pool.shutdown();
       while(!pool.isTerminated()){  
           //wait for all tasks to finish  
       }  
       System.out.println("账号"+ account.getAccoutNo() +",最后金额为:"+account.getMoney());  
   }
}
class Operation implements Runnable{
	
	private Account account;//账号
		
	private String type;
	
	Operation(Account account,String type){
		this.account = account;
		this.type = type;
	}
	
	public void run() {
	    if ("take".equals(type)) { //每次取100元
	    	 //获取写锁  
	    	account.getLock().writeLock().lock();
	    	account.setMoney(account.getMoney() -100);
	    	System.out.println( "取走100元,账号"+ account.getAccoutNo()+" 还有"+account.getMoney()+"元");
	    	account.getLock().writeLock().unlock();
	    	
	    }
	    else if ("query".equals(type)) {
	    	 //获取写锁  
	    	account.getLock().readLock().lock();
	    	System.out.println( "查询账号"+ account.getAccoutNo()+" 还有"+account.getMoney()+"元");
	    	account.getLock().readLock().unlock();
	    	
	    }
	    else if ("save".equals(type)) {
	    	 //获取写锁  
	    	account.getLock().writeLock().lock();
	    	account.setMoney(account.getMoney() + 100);
	    	System.out.println( "存入100元,账号"+ account.getAccoutNo()+" 还有"+account.getMoney()+"元");
	    	account.getLock().writeLock().unlock();
	    }
	}
	
}
class Account  {
	
	private int money;//账号上的钱
	
	private ReadWriteLock lock;//读写写
	
	private String accoutNo;//账号
	
	Account(ReadWriteLock lock,String accoutNo,int money) {
		this.lock = lock;
		this.accoutNo = accoutNo;
		this.money = money;
	}
	
	public int getMoney() {
		return money;
	}
	public void setMoney(int money) {
		this.money = money;
	}
	public ReadWriteLock getLock() {
		return lock;
	}
	public void setLock(ReadWriteLock lock) {
		this.lock = lock;
	}
	public String getAccoutNo() {
		return accoutNo;
	}
	public void setAccoutNo(String accoutNo) {
		this.accoutNo = accoutNo;
	}	
		
}
输出结果:public interface ReadWriteLock {
    Lock readLock();//返回读锁
    Lock writeLock();//返回写锁
}public class ReentrantReadWriteLock
        implements ReadWriteLock, java.io.Serializable {
    private static final long serialVersionUID = -6992448646407690164L;
    /**读锁*/
    private final ReentrantReadWriteLock.ReadLock readerLock;
    /** 写锁 */
    private final ReentrantReadWriteLock.WriteLock writerLock;
    /** 内部类,在ReentrantLock也有它 */
    final Sync sync;    public ReentrantReadWriteLock() {
        this(false);
    }
    /**
     * 设置读写锁
     */
    public ReentrantReadWriteLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();//是否公平
        readerLock = new ReadLock(this);
        writerLock = new WriteLock(this);
    }    public static class ReadLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = -5992448646407690164L;
        private final Sync sync; //和上面的一样,是同一个类        protected ReadLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }
        public void lock() {
            sync.acquireShared(1); //共享锁
        }
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireSharedInterruptibly(1);//响应中断,跳出阻塞
        }
        public boolean tryLock() {
            return sync.tryReadLock();//取得锁才返回true
        }
        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
        }
        public void unlock() {
            sync.releaseShared(1);//释放锁
        }    public final void acquireShared(int arg) {
        if (tryAcquireShared(arg) < 0)
            doAcquireShared(arg);
    } public static class WriteLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = -4992448646407690164L;
        private final Sync sync;
        protected WriteLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }
        public void lock() {
            sync.acquire(1); //表明只是取得一个锁,但不是独占
        }
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }
在WriteLock锁中的lock方法和ReadLock是有所不同的。WriteLock它是一个独占锁。也就是有线程拿到后,其它线程就得阻塞等待了。    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }标签:
原文地址:http://blog.csdn.net/evankaka/article/details/51932044