上文使用lock接口以及对象,很好的实现了对竞争资源的访问控制,这种锁不区分读写,成为普通锁。为了提高性能,Java提供了读写锁。在读的地方使用读锁,在写的地方使用写锁。在一定程度上提高了程序的执行效率。
Java中读写锁有个接口java.util.concurrent.locks.ReadWriteLock,也有具体的实现ReentrantReadWriteLock,详细的API可以查看JavaAPI文档。
public class Main {
public static void main(String args[]){
//创建并发访问的账户
MyCount myCount=new MyCount("370911199123345123",10000);
//创建一个锁对象
ReadWriteLock readWriteLock=new ReentrantReadWriteLock(false);
//创建一个线程池
ExecutorService executorService= Executors.newCachedThreadPool();
User user1=new User(readWriteLock,"张三",myCount,-2000,false);
User user2=new User(readWriteLock,"李四",myCount,-500,false);
User user3=new User(readWriteLock,"王五",myCount,3000,false);
User user4=new User(readWriteLock,"赵六",myCount,-6000,false);
User user5=new User(readWriteLock,"陈七",myCount,-500,true);
executorService.execute(user1);
executorService.execute(user2);
executorService.execute(user3);
executorService.execute(user4);
executorService.execute(user5);
//关闭线程池
executorService.shutdown();
}
}
/**
* 信用卡用户
*/
class MyCount {
private String oid;//账户
private int cash;//余额
MyCount(String oid,int cash){
this.oid=oid;
this.cash=cash;
}
public String getOid() {
return oid;
}
public void setOid(String oid) {
this.oid = oid;
}
public int getCash() {
return cash;
}
public void setCash(int cash) {
this.cash = cash;
}
@Override
public String toString() {
return "MyCount{" +
"oid='" + oid + '\'' +
", cash=" + cash +
'}';
}
}
/**
* 信用卡账户,可随意透支
*/
class User implements Runnable {
private String name; //用户名
private MyCount myCount;//账户
private int cash; //操作的金额
private ReadWriteLock myLock; //执行操作所需要的对象
private boolean isQuery;//是否查询
User(ReadWriteLock myLock, String name, MyCount myCount, int cash,boolean isQuery){
this.myLock=myLock;
this.name=name;
this.myCount=myCount;
this.cash=cash;
this.isQuery=isQuery;
}
@Override
public void run() {
if(this.isQuery){
//获取读锁
this.myLock.readLock().lock();
System.out.println("读:"+name+"正在查询"+this.myCount+"账户,当前金额为"+this.myCount.getCash());
//释放读锁
this.myLock.readLock().unlock();
}else {
//获取写锁
this.myLock.writeLock().lock();
//执行现金业务
System.out.println(name+"正在操作"+this.myCount+"账户,金额为"+this.cash+",当前金额为"+this.myCount.getCash());
this.myCount.setCash(this.myCount.getCash()+this.cash);
System.out.println(name+"操作"+this.myCount+"账户成功,金额为"+this.cash+",当前金额为"+this.myCount.getCash());
//释放写锁
this.myLock.writeLock().unlock();
}
}
}