国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java中的鎖

gaara / 2215人閱讀

摘要:當(dāng)前線程在超時(shí)時(shí)間內(nèi)被中斷超時(shí)時(shí)間結(jié)束,返回釋放鎖獲取等待通知組件,該組件和當(dāng)前的鎖綁定,當(dāng)前線程只有獲取了鎖,才能調(diào)用該組件的方法,調(diào)用后,當(dāng)前線程將釋放鎖。同步器是實(shí)現(xiàn)鎖的關(guān)鍵,在鎖的實(shí)現(xiàn)中聚合同步器,利用同步器實(shí)現(xiàn)鎖的語義。

本文在參考java并發(fā)編程實(shí)戰(zhàn)后完成,參考內(nèi)容較多

Java中的鎖

鎖是用來控制多線程訪問共享資源的方式,一個(gè)鎖能夠防止多個(gè)線程同事訪問共享資源。在Lock接口出現(xiàn)之前,Java程序是通過synchronized來實(shí)現(xiàn)鎖功能的,在JDK1.5之后,新增的Lock接口可以實(shí)現(xiàn)鎖功能,他的功能與Synchronized類似,但是需要顯式的獲取和釋放鎖,他失去了隱式獲取釋放鎖的便捷性,但是可操作性更強(qiáng),同時(shí)具有可中斷獲取鎖以及超時(shí)獲取鎖的特性。

Lock接口

Lock接口提供了幾個(gè)synchronized不具備的主要特性:

嘗試非阻塞的獲取鎖

能被中斷的獲取鎖

超時(shí)獲取鎖

Lock是一個(gè)接口,定義如下:

package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;

/**
 * @see ReentrantLock
 * @see Condition
 * @see ReadWriteLock
 *
 * @since 1.5
 * @author Doug Lea
 */
public interface Lock {

    /**
     * 線程獲取鎖,如果獲取鎖失敗,線程無法向下執(zhí)行
     */
    void lock();

    /**
     * 可中端的獲取鎖,和lock()相比這個(gè)方法可以響應(yīng)中斷,就是在獲取鎖的過程中可以中斷當(dāng)前線程
     */
    void lockInterruptibly() throws InterruptedException;

    /**
     * 嘗試非阻塞的獲取鎖,調(diào)用該方法后立刻返回,獲取鎖成功返回true,否則返回false
     */
    boolean tryLock();

    /**
     * 超時(shí)的獲取鎖,在發(fā)生下面的情況下會返回:
     * 1、在超時(shí)時(shí)間范圍內(nèi)獲取鎖成功立刻返回。2、當(dāng)前線程在超時(shí)時(shí)間內(nèi)被中斷 3、超時(shí)時(shí)間結(jié)束,返回false
     */
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

    /**
     * 釋放鎖
     */
    void unlock();

    /**
     * 獲取等待通知組件,該組件和當(dāng)前的鎖綁定,當(dāng)前線程只有獲取了鎖,才能調(diào)用該組件的wait方法,調(diào)用后,當(dāng)前線程將釋放鎖。
     */
    Condition newCondition();
}
隊(duì)列同步器
隊(duì)列同步器AbstractQueuedSynchronizer,是構(gòu)建鎖或者其他同步組件的基礎(chǔ)框架,他使用int成員變量表示同步狀態(tài)(這個(gè)同步狀態(tài)在不同的同步組件中表示的含義會有差異),通過內(nèi)置的FIFO隊(duì)列完成線程獲取資源的排隊(duì)工作。

同步器使用的主要方式是通過繼承并實(shí)現(xiàn)它定義的抽象方法來管理同步狀態(tài)。隊(duì)列同步器提供了操作同步狀態(tài)的方法,可以保證狀態(tài)的修改是線程安全的,同步器支持獨(dú)占的獲取同步狀態(tài),也支持共享式的獲取。

同步器是實(shí)現(xiàn)鎖的關(guān)鍵,在鎖的實(shí)現(xiàn)中聚合同步器,利用同步器實(shí)現(xiàn)鎖的語義。鎖是面向使用這的,他定義了使用者與鎖交互的接口,隱藏了實(shí)現(xiàn)細(xì)節(jié);同步器面向的是鎖的實(shí)現(xiàn)者,他簡化了鎖的實(shí)現(xiàn)方式,屏蔽了同步狀態(tài)管理、線程排隊(duì),等待喚醒等底層操作。

AbstractQueuedSynchronizer的定義:

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable

//同步器提供的修改活訪問狀態(tài)的方法

//獲取當(dāng)前同步狀態(tài)
protected final int getState() {
    return state;
}
//設(shè)置當(dāng)前同步狀態(tài)
protected final void setState(int newState) {
    state = newState;
}
//使用CAS設(shè)置當(dāng)前狀態(tài),可以保證設(shè)置狀態(tài)的原子性
protected final boolean compareAndSetState(int expect, int update) {
    // See below for intrinsics setup to support this
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

同步器的設(shè)計(jì)是基于模版方法模式的,使用者需要繼承同步器并重寫指定的方法,隨后將同步器組合在自定的同步組件實(shí)現(xiàn)中,并調(diào)用同步器提供的模版方法,而這些模版方法將會調(diào)用使用者重寫的方法

ReentrantLock

ReentrantLock是Java中提供的另一種鎖的實(shí)現(xiàn).他通過調(diào)用lock()方法獲取鎖;調(diào)用unlock()方法釋放鎖。
ReentrantLock的實(shí)現(xiàn)依賴于Java同步框架AbstractQueuedSynchronizer,AQS使用一個(gè)整形的volatile變量(命名為state)來維護(hù)同步狀態(tài),volatile變量是ReentrantLock內(nèi)存語義實(shí)現(xiàn)的關(guān)鍵。

ReentrantLock分為公平鎖和非公平鎖。

公平鎖:每個(gè)線程搶占鎖的順序?yàn)橄群笳{(diào)用lock方法的順序依次獲取鎖

每個(gè)線程搶占鎖的順序不定,誰運(yùn)氣好,誰就獲取到鎖,和調(diào)用lock方法的先后順序無關(guān)。

ReentrantLock的類圖如下:

ReentrantLock實(shí)現(xiàn)了Lock接口,內(nèi)部有三個(gè)內(nèi)部類,Sync、NonfairSync、FairSync,Sync是一個(gè)抽象類型,它繼承AbstractQueuedSynchronizer,這個(gè)AbstractQueuedSynchronizer是一個(gè)模板類,它實(shí)現(xiàn)了許多和鎖相關(guān)的功能,并提供了鉤子方法供用戶實(shí)現(xiàn),比如tryAcquire,tryRelease等。Sync實(shí)現(xiàn)了AbstractQueuedSynchronizer的tryRelease方法。NonfairSync和FairSync兩個(gè)類繼承自Sync,實(shí)現(xiàn)了lock方法,然后分別公平搶占和非公平搶占針對tryAcquire有不同的實(shí)現(xiàn)。

首先分析公平鎖:
ReentrantLock lock = new ReentrantLock(true);公平鎖聲明,如果不為true,或者使用默認(rèn),那么是非公平鎖。
加鎖lock()方法的調(diào)用軌跡如下:

ReentrantLock.lock()

sync.lock() [ReentrantLock.FairSync.lock()]

AbstractQueuedSynchronizer.acquire(int arg) [arg = 1]

ReentrantLock.FairSync.tryAcquire(int acquires);

第4步是加鎖的關(guān)鍵步驟:

protected final boolean tryAcquire(int acquires) {
    //獲取當(dāng)前嘗試獲取鎖的線程
    final Thread current = Thread.currentThread();
    //獲取AQS中的volatile變量state
    int c = getState();
    if (c == 0) {
        //判斷隊(duì)列之前是否有其他的線程在等待
        if (!hasQueuedPredecessors() &&
            compareAndSetState(0, acquires)) {
            //設(shè)置鎖的持有者為當(dāng)前線程
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    //如果當(dāng)前線程已經(jīng)獲取了鎖,那么進(jìn)行鎖重入
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0)
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}
CAS + volatile 構(gòu)成了AQS以及原子變量類。
JDK文檔對CAS的說明:如果當(dāng)前狀態(tài)值與預(yù)期值相等,則以原子的方式講同步狀態(tài)設(shè)置為給定的更新值,此操作具有volatile讀和寫的內(nèi)存語義。這意味著編譯器不能對CAS與CAS前面和后面的任意內(nèi)存操作重排序。CAS操作對應(yīng)的本地方法最終對應(yīng)的處理器源代碼回有一個(gè)Atomic::cmpxchg指令。程序回根據(jù)當(dāng)前處理器的類型來決定是否為cmpxchg指令添加lock前綴。如果是多處理器上運(yùn)行,那么添加Lock前綴,如果是單處理器那么就會省略。lock前綴會確保內(nèi)存的讀寫改操作原子執(zhí)行。(但處理器自身會維護(hù))
【補(bǔ)充volatile的內(nèi)存語義:1、在程序中,當(dāng)?shù)谝粋€(gè)操作為普通變量的讀或?qū)憰r(shí),如果第二個(gè)操作為volatile寫,則編譯器不能重拍下這兩個(gè)操作 2、當(dāng)?shù)诙€(gè)操作為volatile寫時(shí),不管第一個(gè)操作是什么,都不能重排序。這個(gè)規(guī)則確保volatile寫之前的操作不會被編譯器重排序到volatile寫之后  3、當(dāng)?shù)谝粋€(gè)操作是volatile讀時(shí),不管第二個(gè)操作是什么,都不能重排序,這個(gè)規(guī)則確保volatile讀之后的操作不會被編譯器重排序到volatile讀之前  4、當(dāng)?shù)谝粋€(gè)操作是volatile寫,第二個(gè)操作是volatile讀時(shí),不能重排序】
讀寫鎖

ReentrantLock是支持可重入的排他鎖,這些鎖在同一時(shí)刻只允許一個(gè)線程進(jìn)行訪問,而讀寫鎖在同一時(shí)刻可以允許多個(gè)讀線程訪問,但是在寫線程訪問時(shí),所有和讀線程和其他的寫線程均被阻塞。讀寫鎖維護(hù)了兩個(gè)鎖,一個(gè)讀鎖,一個(gè)寫鎖,通過讀寫鎖,可以提高兵法性能。

Java中提供的讀寫鎖的實(shí)現(xiàn)是ReentrantReadWriteLock,提供的特性如下:

公平性選擇,支持公平和非公平的鎖獲取方式

重進(jìn)入

鎖降級 遵循獲取寫鎖,獲取讀鎖再釋放寫鎖的次序,寫鎖能夠降級成讀鎖。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/74594.html

相關(guān)文章

  • Java的鎖

    摘要:中的鎖鎖像同步塊一樣,是一種線程同步機(jī)制,但比中的同步塊更復(fù)雜。這意味著如果一個(gè)線程進(jìn)入了代碼中的同步塊,并因此獲得了該同步塊使用的同步對象對應(yīng)的管程上的鎖,那么這個(gè)線程可以進(jìn)入由同一個(gè)管程對象所同步的另一個(gè)代碼塊。 Java中的鎖 showImg(http://segmentfault.com/img/bVbOvK); 鎖像synchronized同步塊一樣,是一種線程同步機(jī)制,...

    paulquei 評論0 收藏0
  • java并發(fā)編程學(xué)習(xí)1--基礎(chǔ)知識

    摘要:死亡狀態(tài)線程退出有可能是正常執(zhí)行完成也有可能遇見異常退出。類有新建與死亡狀態(tài)返回其余狀態(tài)返回判斷線程是否存活。線程因某些原因進(jìn)入阻塞狀態(tài)。執(zhí)行同步代碼塊的過程中執(zhí)行了當(dāng)前線程放棄開始睡眠進(jìn)入就緒狀態(tài)但是不會釋放鎖。 【java內(nèi)存模型簡介 JVM中存在一個(gè)主存區(qū)(Main Memory或Java Heap Memory),Java中所有變量都是存在主存中的,對于所有線程進(jìn)行共享,而每個(gè)...

    huangjinnan 評論0 收藏0
  • Java的鎖之樂觀鎖與悲觀鎖

    摘要:解決上問題在變量前添加版本號,將變成循環(huán)時(shí)間長開銷大,因?yàn)樽孕枰闹荒鼙WC一個(gè)共享變量的原子操作分類二重入鎖支持重進(jìn)入的鎖,排它鎖分類三讀寫鎖一對鎖,讀鎖,寫鎖,在同一時(shí)刻允許多線程訪問 1、 分類一:樂觀鎖與悲觀鎖   a)悲觀鎖:認(rèn)為其他線程會干擾本身線程操作,所以加鎖 i.具體表現(xiàn)形式:synchronized關(guān)鍵字和lock實(shí)現(xiàn)類 ...

    huangjinnan 評論0 收藏0
  • 淺談Java并發(fā)編程系列(七) —— 深入解析synchronized關(guān)鍵字

    摘要:第一個(gè)字被稱為。經(jīng)量級鎖的加鎖過程當(dāng)一個(gè)對象被鎖定時(shí),被復(fù)制到當(dāng)前嘗試獲取鎖的線程的線程棧的鎖記錄空間被復(fù)制的官方稱為。根據(jù)鎖對象目前是否處于被鎖定狀態(tài),撤銷偏向后恢復(fù)到未鎖定或經(jīng)量級鎖定狀態(tài)。 Synchronized關(guān)鍵字 synchronized的鎖機(jī)制的主要優(yōu)勢是Java語言內(nèi)置的鎖機(jī)制,因此,JVM可以自由的優(yōu)化而不影響已存在的代碼。 任何對象都擁有對象頭這一數(shù)據(jù)結(jié)構(gòu)來支持鎖...

    piglei 評論0 收藏0
  • Java并發(fā)總結(jié)

    摘要:限期阻塞調(diào)用方法等待時(shí)間結(jié)束或線程執(zhí)行完畢。終止?fàn)顟B(tài)線程執(zhí)行完畢或出現(xiàn)異常退了。和都會檢查線程何時(shí)中斷,并且在發(fā)現(xiàn)中斷時(shí)提前放回。工廠方法將線程池的最大大小設(shè)置為,而將基本大小設(shè)置為,并將超時(shí)大小設(shè)置為分鐘。 wait()、notify()、notifyAll() Object是所有類的基類,它有5個(gè)方法組成了等待、通知機(jī)制的核心:notify()、notifyAll()、wait()...

    szysky 評論0 收藏0

發(fā)表評論

0條評論

gaara

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<