文章目錄
- 一 簡介:
- 構造方法
-
- NonfairSync 非公平鎖
- FairSync 公平鎖
- Sync
- Lock 的方法
-
- lock()
- unlock()
- newCondition()
- tryLock()
- lockInterruptibly()
- ReentrantLock 的方法
-
- isLocked()
- isFair()
源碼來自 jdk1.6
一 簡介:
一個可重入的互斥鎖 Lock,它具有與使用 synchronized 方法和語句所通路的隐式螢幕鎖相同的一些基本行為和語義,但功能更強大。
ReentrantLock 将由最近成功獲得鎖,并且還沒有釋放該鎖的線程所擁有。當鎖沒有被另一個線程所擁有時,調用 lock 的線程将成功擷取該鎖并傳回。如果目前線程已經擁有該鎖,此方法将立即傳回。可以使用 isHeldByCurrentThread() 和 getHoldCount() 方法來檢查此情況是否發生。
此類的構造方法接受一個可選的公平 參數。當設定為 true 時,在多個線程的争用下,這些鎖傾向于将通路權授予等待時間最長的線程。否則此鎖将無法保證任何特定通路順序。與采用預設設定(使用不公平鎖)相比,使用公平鎖的程式在許多線程通路時表現為很低的總體吞吐量(即速度很慢,常常極其慢),但是在獲得鎖和保證鎖配置設定的均衡性時差異較小。不過要注意的是,公平鎖不能保證線程排程的公平性。是以,使用公平鎖的衆多線程中的一員可能獲得多倍的成功機會,這種情況發生在其他活動線程沒有被處理并且目前并未持有鎖時。還要注意的是,未定時的 tryLock 方法并沒有使用公平設定。因為即使其他線程正在等待,隻要該鎖是可用的,此方法就可以獲得成功。
建議總是 立即實踐,使用 lock 塊來調用 try,在之前/之後的構造中,最典型的代碼如下:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
除了實作 Lock 接口,此類還定義了 isLocked 和 getLockQueueLength 方法,以及一些相關的 protected 通路方法,這些方法對檢測和監視可能很有用。
該類的序列化與内置鎖的行為方式相同:一個反序列化的鎖處于解除鎖定狀态,不管它被序列化時的狀态是怎樣的。
此鎖最多支援同一個線程發起的 2147483648 個遞歸鎖。試圖超過此限制會導緻由鎖方法抛出的 Error。
構造方法
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = (fair)? new FairSync() : new NonfairSync();
}
NonfairSync 非公平鎖
同步對象以進行非公平鎖定
final static class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
FairSync 公平鎖
同步對象以進行公平鎖定
final static class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (isFirst(current) &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
Sync
此鎖的同步控制基礎。 在下面轉換為公平和非公平版本。 使用AQS狀态表示鎖定的保持數。
static abstract class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* Performs {@link Lock#lock}. The main reason for subclassing
* is to allow fast path for nonfair version.
*/
abstract void lock();
/**
* Performs non-fair tryLock. tryAcquire is
* implemented in subclasses, but both need nonfair
* try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
// Methods relayed from outer class
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
final boolean isLocked() {
return getState() != 0;
}
/**
* Reconstitutes this lock instance from a stream.
* @param s the stream
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
Lock 的方法
lock()
public void lock() {
sync.lock();
}
unlock()
public void unlock() {
sync.release(1);
}
newCondition()
public Condition newCondition() {
return sync.newCondition();
}
tryLock()
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
tryLock(long, TimeUnit)
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
lockInterruptibly()
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
ReentrantLock 的方法
isLocked()
public boolean isLocked() {
return sync.isLocked();
}
isFair()
public final boolean isFair() {
return sync instanceof FairSync;
}
持續更新…