标签:
摘要:本文主要讲了读写锁。
一、读写锁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