在上文中提到了Lock接口以及對象,使用它,很優雅的控制了競爭資源的安全訪問,可是這種鎖不區分讀寫,稱這種鎖爲普通鎖。爲了提升性能,Java提供了讀寫鎖,在讀的地方使用讀鎖,在寫的地方使用寫鎖,靈活控制,在必定程度上提升了程序的執行效率。java
Java中讀寫鎖有個接口java.util.concurrent.locks.ReadWriteLock,也有具體的實現ReentrantReadWriteLock,詳細的API能夠查看JavaAPI文檔。安全
下面這個例子是在文例子的基礎上,將普通鎖改成讀寫鎖,並添加帳戶餘額查詢的功能,代碼以下:併發
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Java線程:鎖
*
* @author leizhimin 2009-11-5 10:57:29
*/
public class Test {
public static void main(String[] args) {
//建立併發訪問的帳戶
MyCount myCount = new MyCount("95599200901215522", 10000);
//建立一個鎖對象
ReadWriteLock lock = new ReentrantReadWriteLock(false);
//建立一個線程池
ExecutorService pool = Executors.newFixedThreadPool(2);
//建立一些併發訪問用戶,一個信用卡,存的存,取的取,好熱鬧啊
User u1 = new User("張三", myCount, -4000, lock, false);
User u2 = new User("張三他爹", myCount, 6000, lock, false);
User u3 = new User("張三他弟", myCount, -8000, lock, false);
User u4 = new User("張三", myCount, 800, lock, false);
User u5 = new User("張三他爹", myCount, 0, lock, true);
//在線程池中執行各個用戶的操做
pool.execute(u1);
pool.execute(u2);
pool.execute(u3);
pool.execute(u4);
pool.execute(u5);
//關閉線程池
pool.shutdown();
}
}
/**
* 信用卡的用戶
*/
class User implements Runnable {
private String name; //用戶名
private MyCount myCount; //所要操做的帳戶
private int iocash; //操做的金額,固然有正負之分了
private ReadWriteLock myLock; //執行操做所需的鎖對象
private boolean ischeck; //是否查詢
User(String name, MyCount myCount, int iocash, ReadWriteLock myLock, boolean ischeck) {
this.name = name;
this.myCount = myCount;
this.iocash = iocash;
this.myLock = myLock;
this.ischeck = ischeck;
}
public void run() {
if (ischeck) {
//獲取讀鎖
myLock.readLock().lock();
System.out.println("讀:" + name + "正在查詢" + myCount + "帳戶,當前金額爲" + myCount.getCash());
//釋放讀鎖
myLock.readLock().unlock();
} else {
//獲取寫鎖
myLock.writeLock().lock();
//執行現金業務
System.out.println("寫:" + name + "正在操做" + myCount + "帳戶,金額爲" + iocash +",當前金額爲" + myCount.getCash());
myCount.setCash(myCount.getCash() + iocash);
System.out.println("寫:" + name + "操做" + myCount + "帳戶成功,金額爲" + iocash +",當前金額爲" + myCount.getCash());
//釋放寫鎖
myLock.writeLock().unlock();
}
}
}
/**
* 信用卡帳戶,可隨意透支
*/
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 +
'}';
}
}ide
寫:張三正在操做MyCount{oid='95599200901215522', cash=10000}帳戶,金額爲-4000,當前金額爲10000
寫:張三操做MyCount{oid='95599200901215522', cash=6000}帳戶成功,金額爲-4000,當前金額爲6000
寫:張三他弟正在操做MyCount{oid='95599200901215522', cash=6000}帳戶,金額爲-8000,當前金額爲6000
寫:張三他弟操做MyCount{oid='95599200901215522', cash=-2000}帳戶成功,金額爲-8000,當前金額爲-2000
寫:張三正在操做MyCount{oid='95599200901215522', cash=-2000}帳戶,金額爲800,當前金額爲-2000
寫:張三操做MyCount{oid='95599200901215522', cash=-1200}帳戶成功,金額爲800,當前金額爲-1200
讀:張三他爹正在查詢MyCount{oid='95599200901215522', cash=-1200}帳戶,當前金額爲-1200
寫:張三他爹正在操做MyCount{oid='95599200901215522', cash=-1200}帳戶,金額爲6000,當前金額爲-1200
寫:張三他爹操做MyCount{oid='95599200901215522', cash=4800}帳戶成功,金額爲6000,當前金額爲4800
Process finished with exit code 0性能
在實際開發中,最好在能用讀寫鎖的狀況下使用讀寫鎖,而不要用普通鎖,以求更好的性能。this
本文出自 「熔 巖」 博客.net