一、
在JDK1.5之後,在java.util.concurrent.locks的包中提供了另一種實現代碼同步的方法,Lock。
在前面說過,synchronize鎖是一種重量級的,特別耗費資源的鎖。在使用synchronize中,當線程被阻塞或等待處理,但又沒有釋放鎖時,其他線程只能在外面等待,非常影響執行效率。這就需要有一種機制可以不讓等待的線程一直無期限地等待下去(比如只等待一定的時間或者能夠響應中斷),通過Lock就可以辦到。
但是需要注意:
1)Lock需要顯示地獲取和釋放鎖,繁瑣能讓代碼更靈活
2)Synchronized不需要顯示地獲取和釋放鎖,簡單
二、
查看Lock的源碼可以看到,Lock接口主要有這幾個方法:
其中,lock()、lockInterruptibly()、tryLock()和tryLock(long time, TimeUnit unit)是用來獲取鎖的,unlock()是用來釋放鎖的。
2.1 lock()
lock()方式是最常用的獲取鎖的方法。如果當時鎖不可用(被其他線程佔用)則線程等待。由於lock是不會主動釋放鎖的,爲了防止出現死鎖的情況發生,lock()代碼塊必須進行異常捕捉與處理,並在finally中調用unlock()方法來保證鎖的釋放。
private int value;
Lock lock = new ReentrantLock();
public int getNext() {
lock.lock();
int a = 0;
try {
a = value++;
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
return a;
}
2.2 lockInterruptibly()
當通過該方法獲取鎖時,如果鎖可用,則獲取鎖;如果鎖不可用,則當前線程進入等待(休眠)狀態,直到發生以下情況:
1)、對該等待線程調用interrupt()方法,中斷該線程等待狀態
2)、如果當前線程在進入該方法前就調用interrupt()方法,即被設置爲中斷狀態,或者在獲取鎖定時被中斷,則會拋出InterruptedException異常,然後清除中斷狀態。
注意:當線程成功獲取到鎖之後是無法調用interrupt()方法中斷的。因爲interrupt()方法只能中斷被阻塞過程中的線程。
2.3 tryLock()
tryLock()方法是一個返回布爾值的方法,表示在能成功獲取到鎖時返回true;不能獲取到鎖返回false。該方法在無論能否成功獲取到鎖時都會及時的返回,而不會在不能獲取到鎖時等待。
Lock lock = ...;
if (lock.tryLock()) {
try {
// manipulate protected state
} finally {
lock.unlock();
}
} else {
// perform alternative actions
}
}
2.4 tryLock(long time, TimeUnit unit)
tryLock(long time, TimeUnit unit)和tryLock()類似,只是多了兩個參數:
·time : 最長等待解鎖時間
·unit : 時間單位
該方法在調用時需要傳遞等待時間和單位,在等待時間內無法獲取到鎖則返回false,否則則返回true