又是一個基于AQS好用的類,看來下次有必要看看AQS了,正好又是放假。
既然叫顯式鎖,必然也有隱式鎖,也就是所謂的synchronzied關鍵字,它們兩者的區別呢在于使用范圍,synchronzied關鍵字的使用范圍比Lock要小,在Lock的實現類中與synchronzied相近似的類叫ReentrantLock,也叫可重入鎖,待會兒在說看看Lock吧
Lock
是一個接口,主要的實現類有三個 ReadLock(寫鎖),WriteLock(讀鎖),ReentrantLock(可重入鎖)
核心方法:
1、lock():獲取鎖并上鎖。
2、unlock():釋放鎖,未釋放會造成阻塞,一般放在程序的finally代碼塊中。
3、tryLock():嘗試的獲取鎖,帶參數的為超時嘗試獲取鎖。
4、newCondition():獲取到Condition接口的實現類,用于配合Lock實現等待通知功能,每調用一次就獲取一個新的Condition,并非只有一個。
5、 lockInterruptibly():獲取鎖但是可以中斷這個鎖。
使用示例:
static Lock lock = new ReentrantLock();
static int count = 0;public static void main(String [] arg0){lock.lock();//獲取鎖try{count ++ ;}finally{lock.unlock();//釋放鎖}}
//該示例就做一個統計吧
可重入鎖(ReentrantLock)
就是可以重復獲取鎖,但是這種一般出現于遞歸算法,重復獲取了多少次鎖就會釋放多少次鎖。
看一個案例:
static Lock lock = new ReentrantLock();static int count = 0;public synchronized static void addIntger() {count ++;while(count<10) {addIntger();//可重入鎖}}public static void addLockIntger() {lock.lock();try {count ++;while(count<10) {addLockIntger();//可重入鎖}} finally {lock.unlock();}}public static void main(String[] args) {System.out.println(count);addLockIntger();System.out.println(count);}
公平鎖和非公平鎖
公平鎖(new FairSync()):即同一時刻去多個線程請求鎖,先到先得,排隊獲取鎖即為公平鎖,未獲取到鎖的線程會被掛起(非阻塞等待,是會進入到AQS的尾隊列等待,跟非公平鎖比,耗時就是花費在這里),等到鎖釋放后按照順序獲取鎖,所以與非公平鎖相比,更耗時。
非公平鎖(new NonfairSync()):即同一時刻多個線程去請求鎖,不是按照先到先的順序獲取鎖即為非公平鎖,無需進入AQS隊列等待,運行速度更快,創建Lock對象默認為非公平鎖。
這兩種鎖都繼承了AQS(不得不說Doug Lea大師的強大),公平鎖適合在按順序執行的場景。
讀寫鎖(ReadWriteLock)
ReadWriteLock并沒有繼承Lock接口,而是在它的實現類中ReentrantReadWriteLock有兩個內部類卻繼承了Lock接口,即為ReadLock和WriteLock,這兩均實現了AQS抽象類。
這個種鎖使用的場景為讀多寫少的場景,在獲取寫鎖時,讀寫鎖都會進入阻塞狀態,而獲取讀鎖并不會進入阻塞狀態。
public interface ReadWriteLock {/*** Returns the lock used for reading.** @return the lock used for reading*/Lock readLock();/*** Returns the lock used for writing.** @return the lock used for writing*/Lock writeLock();
}
Condition
可以配合Lock使用等待通知模式,這里就不演示啦,與之前的wait()和notify/notifyAll()相近似,看一下這個接口中的方法定義:
1、await():類似于Object的wait()等待。
2、awaitUninterruptibly():這個表示等待不可中斷,其他的等待都可以被中斷。
3、awaitNanos(long):超時等待。
4、awaitUntil(Date):可指定時間超時等待,與上面幾種超時方法差不多。
5、signal():類似與Object中的notify()。
6、signalAll():類似與Object中的notifyAll()。
LockSupport
是Lock的支持類,里面都是靜態方法
主要是用來阻塞、喚醒一個線程
1、park():阻塞當前線程
2、unpark(Thread t):喚醒指定線程
park也有其他帶參數的方法,基本都是不同形式的超時等待方法。
好啦差不多就這樣了,Lock的用途還是挺廣泛的,在很多開源包都能看見這個的身影,比如阿里的Druid連接池中就用到了。寫的并不是很好,各路大佬可以在評論里面補充咯