2019-08-16-鎖的分類

鎖的分類:

一耍攘,線程是否需要鎖住同步資源

廣義角度上的概念,對于同一個數(shù)據(jù)的并發(fā)操作下

  • 樂觀鎖

    • 認為自己使用數(shù)據(jù)的時候堪滨,不會有別的線程來修改數(shù)據(jù)胯陋,只是會在更新數(shù)據(jù)的時候,判斷數(shù)據(jù)是否被修改過袱箱,如果沒有修改過遏乔,則直接讀取數(shù)據(jù)操作,否則根據(jù)不同的實現(xiàn)方式來執(zhí)行不同的操作(重試或者報錯)发笔。
    • 樂觀鎖常用無鎖編程來實現(xiàn)盟萨,最常采用的方法就是CAS算法,Java的原子類就是通過CAS算法來實現(xiàn)的了讨。
    • 適合讀較多的場景
  • 樂觀鎖的場景

      AtomicInteger i = new AtomicInteger(1);
      i.incrementAndGet();
    

這里涉及到一個原子類AtomicInteger的CAS算法實現(xiàn)捻激,具體可以看這篇文章AtomicInteger實現(xiàn)原理

  • 悲觀鎖

    • 認為自己使用數(shù)據(jù)的時候,一定會有其他線程對數(shù)據(jù)進行了更新操作前计,所以獲取數(shù)據(jù)的時候一定要先加鎖铺罢,確保數(shù)據(jù)不會被修改。
    • Java中的synchornized關(guān)鍵字和Lock的子類實現(xiàn)都是悲觀鎖残炮。
    • 適合寫較多的場景韭赘。
  • 悲觀鎖的場景-(需要保證多個線程使用的是同一個鎖)

方式一

private ReentrantLock lock = new ReentrantLock();
private void doLock() {
    //嘗試獲取鎖
    lock.lock();
    //doSomeThing();
    lock.unlock();
    //執(zhí)行完unLock釋放鎖
}

方式二

private Object syncLock = new Object();
private void syncLock() {
    //嘗試獲取鎖
    synchronized (syncLock) {
        doSomeThing();
    }
    //執(zhí)行完同步塊,自動釋放鎖
}

二势就,鎖住同步資源泉瞻,線程是否需要阻塞

  • 阻塞
  • 不阻塞

介紹自旋鎖之前,我們先說明一個概念苞冯,Java線程的阻塞和喚醒袖牙,都是需要操作系統(tǒng)來切換CPU狀態(tài)來實現(xiàn)的,這種狀態(tài)切換需要耗費處理器時間舅锄,如果同步塊的操作的內(nèi)容過于簡單鞭达,狀態(tài)轉(zhuǎn)換的耗時可能比執(zhí)行操作的時間更長

  • 自旋鎖
    • 不放棄CPU時間片,通過自旋等待鎖釋放皇忿,降低因CPU狀態(tài)切換的的消耗
    • 自旋獲取成功之后畴蹭,操作同步資源
    • 失敗的情況下,CPU切換狀態(tài)鳍烁,線程休眠
  • 適應(yīng)性自旋鎖
    • 意味這自旋的時間和次數(shù)都不在固定
    • 而是由前一次在同一個鎖上的自旋時間及鎖的擁有者的狀態(tài)來決定
    • 如果對于同一個鎖對象上叨襟,自旋剛剛成功獲得過鎖,并且持有鎖的線程正在運行中幔荒,那么虛擬機就會認為這次自旋也是很有可能再次成功糊闽,進而它將允許自旋等待持續(xù)相對更長的時間
    • 如果對于某個鎖梳玫,自旋很少成功獲得過,那在以后嘗試獲取這個鎖時將可能省略掉自旋過程右犹,直接阻塞線程提澎,避免浪費處理器資源。

三念链,多個線程競爭同步資源的流程細節(jié)有沒有區(qū)別

這四種鎖是指鎖的狀態(tài)盼忌,專門針對synchronized的
首先為什么Synchronized能實現(xiàn)線程同步?

  • 無鎖
    不鎖住資源钓账,多個線程只有一個能修改資源成功碴犬,其他的會重試(主要實現(xiàn)CAS算法)
  • 偏向鎖
    同一個線程操作執(zhí)行同步資源時自動獲得資源
  • 輕量級鎖
    多個線程競爭同步資源時絮宁,沒有獲得資源的線程自旋或者等待資源釋放
  • 重量級鎖
    多個線程競爭同步資源時梆暮,沒有獲得資源的線程阻塞等待喚醒

所以目前鎖一共有4種狀態(tài),級別從低到高依次是:無鎖绍昂、偏向鎖啦粹、輕量級鎖和重量級鎖。鎖狀態(tài)只能升級不能降級窘游。

四唠椭,多個線程競爭資源要不要排隊

  • 公平鎖 需要排隊

    • 多線程根據(jù)申請鎖的順序來獲取鎖
    • 優(yōu)點是等待鎖的線程不會餓死
    • 缺點是整體的吞吐效率相對非公平鎖要低
    • 等待隊列的線程都需要CPU喚醒阻塞線程,開銷比較大
  • 非公平鎖 先嘗試插隊忍饰,失敗了再排隊

    • 申請鎖的線程贪嫂,先嘗試獲取鎖,失敗了再排隊
    • 優(yōu)點是整體的吞吐效率比較好艾蓝,可以減少喚醒線程的開銷
    • 缺點是有線程可能會餓死或者等很久才能獲得鎖
  • ReentrantLock 公平和非公平鎖的實現(xiàn)方式

    • ReentrantLock里面有一個內(nèi)部類Sync力崇,Sync繼承AQS(AbstractQueuedSynchronizer),添加鎖和釋放鎖的大部分操作實際上都是在Sync中實現(xiàn)的

    • Sync有公平鎖FairSync和非公平鎖NonfairSync兩個子類赢织,公平鎖和非公平鎖的實現(xiàn)區(qū)別就是

        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)前線程是否位于同步隊列中的第一個亮靴。如果是則返回true,否則返回false于置。

綜上茧吊,公平鎖就是通過同步隊列來實現(xiàn)多個線程按照申請鎖的順序來獲取鎖,從而實現(xiàn)公平的特性八毯。非公平鎖加鎖時不考慮排隊等待問題搓侄,直接嘗試獲取鎖,所以存在后申請卻先獲得鎖的情況话速。

五休讳,一個線程中的多個流程能否獲得同一把鎖

  • 可重入鎖 :能 可重入鎖又名遞歸鎖

    • 指在同一個線程在外層方法獲取鎖的時候,再進入該線程的內(nèi)層方法會自動獲取鎖(前提鎖對象得是同一個對象或者class)尿孔,不會因為之前已經(jīng)獲取過還沒釋放而阻塞俊柔。

    • Java中ReentrantLock和synchronized都是可重入鎖筹麸,

    • 可重入鎖的一個優(yōu)點是可一定程度避免死鎖。

    • 可重入鎖示例

        private synchronized void doOne(String a) {
            doOnther(a);
        }
        
        private synchronized void doOnther(String b) {
            System.out.println("b = [" + b + "]");
        }
      
  • 非可重入鎖 :不能

六雏婶,多個線程能否共享一把鎖

  • 共享鎖 :能
  • 排它鎖 :不能

參考文章

其他文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末物赶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子留晚,更是在濱河造成了極大的恐慌酵紫,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件错维,死亡現(xiàn)場離奇詭異奖地,居然都是意外死亡,警方通過查閱死者的電腦和手機赋焕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門参歹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人隆判,你說我怎么就攤上這事犬庇。” “怎么了侨嘀?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵臭挽,是天一觀的道長。 經(jīng)常有香客問我咬腕,道長欢峰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任涨共,我火速辦了婚禮纽帖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘煞赢。我一直安慰自己抛计,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布照筑。 她就那樣靜靜地躺著吹截,像睡著了一般。 火紅的嫁衣襯著肌膚如雪凝危。 梳的紋絲不亂的頭發(fā)上波俄,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音蛾默,去河邊找鬼懦铺。 笑死,一個胖子當(dāng)著我的面吹牛支鸡,可吹牛的內(nèi)容都是我干的冬念。 我是一名探鬼主播趁窃,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼急前!你這毒婦竟也來了醒陆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤裆针,失蹤者是張志新(化名)和其女友劉穎刨摩,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體世吨,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡澡刹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了耘婚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片罢浇。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖边篮,靈堂內(nèi)的尸體忽然破棺而出己莺,到底是詐尸還是另有隱情奏甫,我是刑警寧澤戈轿,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站阵子,受9級特大地震影響思杯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜挠进,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一色乾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧领突,春花似錦暖璧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至金砍,卻和暖如春局蚀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背恕稠。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工琅绅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鹅巍。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓千扶,卻偏偏與公主長得像料祠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子澎羞,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容