溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

ReentrantLock源碼的示例分析

發(fā)布時間:2021-09-15 11:14:00 來源:億速云 閱讀:108 作者:小新 欄目:大數(shù)據(jù)

這篇文章主要介紹了ReentrantLock源碼的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

Lock

鎖是用來控制多個線程訪問共享資源的方式,一個鎖能夠防止多個線程同時共享資源。
Lock需要顯式的獲取和釋放鎖,擁有了獲取鎖和釋放鎖的可操作性,可中斷的獲取鎖以及超時獲取鎖等多種同步特性
Lock的實(shí)現(xiàn)基本都是通過聚合一個同步器的子類來實(shí)現(xiàn)的。

隊列同步器AbstractQueuedSynchronizer

使用一個int變量來表示同步狀態(tài)
內(nèi)置一個FIFO隊列來完成資源的獲取以及線程的排隊工作
同步器本身未實(shí)現(xiàn)任何同步接口,僅僅是定義了若干同步狀態(tài)獲取和釋放的方法來供自定義同步組件使用
即支持獨(dú)占式獲取同步狀態(tài),也支持共享式獲取同步狀態(tài)

重入鎖

支持一個線程對資源的重復(fù)加鎖
再次獲取鎖:通過判斷當(dāng)前線程是否為獲取鎖的線程來決定獲取操作是否成功,如果是獲取鎖的線程再次請求,則同步狀態(tài)增加并返回成功
鎖的最終釋放:鎖被釋放時,計數(shù)自減,當(dāng)計數(shù)等于0表示鎖已經(jīng)成功釋放

讀寫鎖

讀寫鎖維護(hù)了一堆鎖,一個讀鎖,一個寫鎖。
通過分離讀鎖和寫鎖,使并發(fā)性相比一般的排它鎖有了很大提升,因為大多數(shù)場景讀多于寫
讀鎖:
支持重進(jìn)入的共享鎖,當(dāng)前線程獲取了寫鎖或者鎖未獲取,當(dāng)前線程增加讀狀態(tài),成功獲取讀鎖
寫鎖:
支持重入的排他鎖,如果存在讀鎖,則寫鎖不能獲取
鎖降級:指的是寫鎖降級為讀鎖

LockSupport工具

當(dāng)需要阻塞或者喚醒一個線程的時候,都會使用該工具類來完成相應(yīng)工作

Condition接口

提供類似Object的監(jiān)視器方法,與Lock配合實(shí)現(xiàn)等待.通知模式
依賴Lock對象,獲取一個Condition必須通過Lock的NewCondition()方法
是同步器AbstractQueuedSynchronizer的內(nèi)部類
每個Condition包含一個隊列,該隊列是Condition對象實(shí)現(xiàn)等待.通知功能的關(guān)鍵
調(diào)用await()方法,會使當(dāng)前線程進(jìn)入等待隊列,并且釋放鎖,同時線程變成等待狀態(tài)
調(diào)用signal()方法,將會喚醒在隊列中等待時間最長的節(jié)點(diǎn)
 

public interface Lock {
    // 省略大部分代碼 
    /**
     * Condition 跟Lock綁定
     */
    Condition newCondition();
}

// 通過實(shí)現(xiàn)Lock定義的接口,以及聚合一個隊列同步器AbstractQueuedSynchronizer實(shí)現(xiàn)
public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;
    /** Synchronizer providing all implementation mechanics */
    private final Sync sync;

    /**
     * 定義一個內(nèi)部類,繼承同步器
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;
	}
}

/**
 * 無參數(shù)構(gòu)造方法,默認(rèn)是非公平鎖
 */
public ReentrantLock() {
	sync = new NonfairSync();
}

/**
 * 有參數(shù)構(gòu)造方法,參數(shù)傳遞true,則為公平鎖
 */
public ReentrantLock(boolean fair) {
	sync = fair ? new FairSync() : new NonfairSync();
}

// 獲取Condition是通過Lock內(nèi)部的方法在調(diào)用了同步器內(nèi)部的方法實(shí)現(xiàn)的
public Condition newCondition() {
    return sync.newCondition();
}
public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;
    /** Synchronizer providing all implementation mechanics */
    private final Sync sync;

    /**
     * ......
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;
        // ......
		// 獲取Condition對象,是同步器的內(nèi)部類
        final ConditionObject newCondition() {
            return new ConditionObject();
        }
        // ......
    }
}

// 當(dāng)鎖可用,并且當(dāng)前線程沒有持有該鎖,直接獲取鎖并把count set為1.
// 當(dāng)鎖可用,并且當(dāng)前線程已經(jīng)持有該鎖,直接獲取鎖并把count增加1.
// 當(dāng)鎖不可用,那么當(dāng)前線程被阻塞,休眠一直到該鎖可以獲取,然后把持有count設(shè)置為1.
public void lock() {
	sync.lock();
}
 /**
 * 非公平鎖加鎖
 */
static final 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))
			// 設(shè)置當(dāng)前線程
			setExclusiveOwnerThread(Thread.currentThread());
		else
			acquire(1);
	}

	protected final boolean tryAcquire(int acquires) {
		return nonfairTryAcquire(acquires);
	}
}
// 標(biāo)識位進(jìn)行交換
protected final boolean compareAndSetState(int expect, int update) {
	// See below for intrinsics setup to support this
	return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

public final void acquire(int arg) {
	if (!tryAcquire(arg) &&
		acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
		selfInterrupt();
}

/**
 *添加進(jìn)等待隊列
 */
final boolean acquireQueued(final Node node, int arg) {
	boolean failed = true;
	try {
		boolean interrupted = false;
		for (;;) {
			final Node p = node.predecessor();
			if (p == head && tryAcquire(arg)) {
				setHead(node);
				p.next = null; // help GC
				failed = false;
				return interrupted;
			}
			if (shouldParkAfterFailedAcquire(p, node) &&
				parkAndCheckInterrupt())
				interrupted = true;
		}
	} finally {
		if (failed)
			cancelAcquire(node);
	}
}
/**
 * Convenience method to interrupt current thread.
 */
static void selfInterrupt() {
	Thread.currentThread().interrupt();
}

	
/**
 * 公平鎖
 */
static final 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 (!hasQueuedPredecessors() &&
				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;
	}
}
 /* 
 * 等待隊列是空,或者當(dāng)前頭節(jié)點(diǎn)就是當(dāng)前線程
 */
public final boolean hasQueuedPredecessors() {
	// The correctness of this depends on head being initialized
	// before tail and on head.next being accurate if the current
	// thread is first in queue.
	Node t = tail; // Read fields in reverse initialization order
	Node h = head;
	Node s;
	return h != t &&
		((s = h.next) == null || s.thread != Thread.currentThread());
}

// 當(dāng)鎖可用,并且當(dāng)前線程沒有持有該鎖,直接獲取鎖并把count set為1.
// 當(dāng)鎖可用,并且當(dāng)前線程已經(jīng)持有該鎖,直接獲取鎖并把count增加1.
// 獲取鎖時,如果其他線程持有該鎖,無可用鎖資源,直接返回false,這時候線程不用阻塞等待,可以先去做其他事情
public boolean tryLock() {
	return sync.nonfairTryAcquire(1);
}

//當(dāng)獲取鎖時,鎖資源在超時時間之內(nèi)變?yōu)榭捎茫⑶以诘却龝r沒有被中斷,那么當(dāng)前線程成功獲取鎖,返回true,同時當(dāng)前線程持有鎖的count設(shè)置為1.
// 當(dāng)獲取鎖時,在超時時間之內(nèi)沒有鎖資源可用,那么當(dāng)前線程獲取失敗,不再繼續(xù)等待,返回false.
// 當(dāng)獲取鎖時,在超時等待時間之內(nèi),被中斷了,那么拋出InterruptedException,不再繼續(xù)等待.
// 當(dāng)獲取鎖時,在超時時間之內(nèi)鎖可用,并且當(dāng)前線程之前已持有該鎖,那么成功獲取鎖,同時持有count加1.
public boolean tryLock(long timeout, TimeUnit unit)
		throws InterruptedException {
	return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
// 釋放鎖
public void unlock() {
	sync.release(1);
}
/**
 * 釋放鎖方法
 */
AbstractQueuedSynchronizer.java 的方法
public final boolean release(int arg) {
	if (tryRelease(arg)) {
		Node h = head;
		if (h != null && h.waitStatus != 0)
			unparkSuccessor(h);
		return true;
	}
	return false;
}

// ReentrantLock.java的內(nèi)部類Sync的方法	
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;
}

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“ReentrantLock源碼的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI