国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【JavaEE】Java中復(fù)雜的Synchronized關(guān)鍵字

這篇具有很好參考價值的文章主要介紹了【JavaEE】Java中復(fù)雜的Synchronized關(guān)鍵字。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

?一、synchronized的特性

(1)互斥

(2)刷新內(nèi)存

(3)可重入

二、synchronized的使用

(1)修飾普通方法

(2)修飾靜態(tài)方法

(3)修飾代碼塊

三、synchronized的鎖機制

(1)基本特點

(2)加鎖工作過程

1.偏向鎖

2.輕量級鎖

3.重量級鎖

(3)優(yōu)化操作

1.鎖消除

2.鎖粗化

四、synchronized和volatile的區(qū)別


?文章來源地址http://www.zghlxwxcb.cn/news/detail-803304.html

?一、synchronized的特性

(1)互斥

? ? ? ? ?synchronized 通過互斥達到原子性(線程安全的四大特性之一)

????????synchronized 會起到互斥效果,某個線程執(zhí)行到某個對象的 synchronized 中時,其他線程如果也執(zhí)行到同一個對象 synchronized 就會阻塞等待。同一時間,只能一個線程擁有這把鎖,去執(zhí)行代碼。
1.進入 synchronized 修飾的代碼塊, 相當(dāng)于 加鎖。
2.退出 synchronized 修飾的代碼塊, 相當(dāng)于 解鎖。

synchronized void increase(){//進入方法內(nèi)部,相當(dāng)于針對當(dāng)前對象?
? ? ? ? count++;

}//執(zhí)行完畢相當(dāng)于針對當(dāng)前對象“解鎖”

????????synchronized用的鎖是存在Java對象頭里的。synchronized的底層是使用操作系統(tǒng)的mutex lock實現(xiàn)的。
????????可以粗略理解成, 每個對象在內(nèi)存中存儲的時候, 都存有一塊內(nèi)存表示當(dāng)前的 "鎖定" 狀態(tài)。如果當(dāng)前是 "未鎖定" 狀態(tài), 那么就可以使用, 使用時需要設(shè)為 "鎖定" 狀態(tài)。如果當(dāng)前是 "鎖定" 狀態(tài), 那么其他人無法使用, 只能排隊等待。一個線程先上了鎖,其他線程只能等待這個線程釋放。

? ? ? ? 注意點:

????????針對每一把鎖,操作系統(tǒng)內(nèi)部都維護了一個等待隊列。當(dāng)這個鎖被某個線程占有的時候, 其他線程嘗試進行加鎖,就加不上了, 就會阻塞等待, 一直等到之前的線程解鎖之后,由操作系統(tǒng)喚醒一個新的線程,再來獲取到這個鎖。

????????上一個線程解鎖之后, 下一個線程并不是立即就能獲取到鎖。而是要靠操作系統(tǒng)來 "喚醒"。 這也就是操作系統(tǒng)線程調(diào)度的一部分工作。
????????假設(shè)有 A B C 三個線程,線程 A 先獲取到鎖,然后 B 嘗試獲取鎖, 然后 C 再嘗試獲取鎖,此時 B和 C 都在阻塞隊列中排隊等待。 但是當(dāng) A 釋放鎖之后, 雖然 B 比 C 先來的, 但是 B 不一定就能獲取到鎖, 而是和 C 重新競爭,并不遵守先來后到的規(guī)則。

(2)刷新內(nèi)存

????????synchronized 通過加鎖減鎖能保證內(nèi)存可見性。

synchronized 的工作過程:
1. 獲得互斥鎖
2. 從主內(nèi)存拷貝變量的最新副本到工作的內(nèi)存
3. 執(zhí)行代碼
4. 將更改后的共享變量的值刷新到主內(nèi)存
5. 釋放互斥鎖
所以 synchronized 也能保證內(nèi)存可見性。

(3)可重入

?????????synchronized 只能有一定約束,并不能完全禁止指令重排序。synchronized 同步塊對同一條線程來說是可重入的,不會出現(xiàn)自己把自己鎖死的問題。

// 第一次加鎖, 加鎖成功
lock();
// 第二次加鎖, 鎖已經(jīng)被占用, 阻塞等待.
lock();

????????對于把自己鎖死,就是一個線程沒有釋放鎖,然后又嘗試再次加鎖。

????????按照之前對于鎖的設(shè)定, 第二次加鎖的時候會阻塞等待。直到第一次的鎖被釋放, 才能獲取到第二個鎖。釋放第一個鎖也是由該線程來完成, 結(jié)果這個線程已經(jīng)阻塞等待了,也就無法進行解鎖操作。這時候就會死鎖。這樣的鎖稱為不可重入鎖。

? ? ? ? Java中的synchronized是可重入鎖,因此不會出現(xiàn)上述問題??芍厝腈i的內(nèi)部,包含了 "線程持有者" 和 "計數(shù)器" 兩個信息。如果某個線程進行加鎖的時候, 發(fā)現(xiàn)鎖已經(jīng)被人占用, 占用者恰好是自己,那么仍然可以繼續(xù)獲取到鎖, 并讓計數(shù)器自增。解鎖的時候就是當(dāng)計數(shù)器遞減為0的時候, 才真正釋放鎖,這時候鎖才能被別的線程獲取到。

二、synchronized的使用

(1)修飾普通方法

鎖的 SynchronizedDemo 對象

public class SynchronizedDemo {
    public synchronized void methond() {
    }
}

(2)修飾靜態(tài)方法

鎖的 SynchronizedDemo 類的對象
?

public class SynchronizedDemo {
    public synchronized static void method() {
    }
}

(3)修飾代碼塊

明確指定鎖的對象

鎖當(dāng)前對象

public class SynchronizedDemo {
    public void method() {
    synchronized (this) {
        }
    }
}

鎖類對象

public class SynchronizedDemo {
    public void method() {
        synchronized (SynchronizedDemo.class) {
        }
    }
}

????????需要注意的是兩個線程競爭同一把鎖,才會產(chǎn)生阻塞等待。兩個線程分別嘗試獲取兩把不同的鎖,不會產(chǎn)生競爭。

三、synchronized的鎖機制

(1)基本特點

????????只考慮 JDK 1.8,加鎖工作過程:JVM 將 synchronized 鎖分為 無鎖、偏向鎖、輕量級鎖、重量級鎖 狀態(tài)。會根據(jù)情況,進行依次升級。
1. 開始時是樂觀鎖, 如果鎖沖突頻繁, 就轉(zhuǎn)換為悲觀鎖.
2. 開始是輕量級鎖實現(xiàn), 如果鎖被持有的時間較長, 就轉(zhuǎn)換成重量級鎖.
3. 實現(xiàn)輕量級鎖的時候大概率用到的自旋鎖策略
4. 是一種不公平鎖
5. 是一種可重入鎖
6. 不是讀寫鎖

(2)加鎖工作過程

1.偏向鎖

????????第一個嘗試加鎖的線程,優(yōu)先進入偏向鎖狀態(tài)。
????????偏向鎖不是真的 "加鎖", 只是給對象頭中做一個 "偏向鎖的標(biāo)記",記錄這個鎖屬于哪個線程。如果后續(xù)沒有其他線程來競爭該鎖,那么就不用進行其他同步操作了,避免了加鎖解鎖的開銷。如果后續(xù)有其他線程來競爭該鎖,因為剛才已經(jīng)在鎖對象中記錄了當(dāng)前鎖屬于哪個線程了, 很容易識別當(dāng)前申請鎖的線程是不是之前記錄的線程, 那就取消原來的偏向鎖狀態(tài), 進入一般的輕量級鎖狀態(tài)。偏向鎖本質(zhì)上相當(dāng)于 "延遲加鎖"。能不加鎖就不加鎖,盡量來避免不必要的加鎖開銷。但是該做的標(biāo)記還是得做的, 否則無法區(qū)分何時需要真正加鎖。

? ? ? ? 面試中會經(jīng)常問到什么是偏向鎖。偏向鎖不是真的加鎖,而只是在鎖的對象頭中記錄一個標(biāo)記,記錄該鎖所屬的線程。如果沒有其他線程參與競爭鎖,那么就不會真正執(zhí)行加鎖操作,從而降低程序開銷。一旦真的涉及到其他的線程競爭,再取消偏向鎖狀態(tài),進入輕量級鎖狀態(tài)。

2.輕量級鎖

????????隨著其他線程進入競爭,偏向鎖狀態(tài)被消除, 進入輕量級鎖狀態(tài)(自適應(yīng)的自旋鎖)。
此處的輕量級鎖就是通過 CAS 來實現(xiàn)。
????????通過 CAS 檢查并更新一塊內(nèi)存 (比如 null => 該線程引用)。如果更新成功,則認為加鎖成功。如果更新失敗, 則認為鎖被占用, 繼續(xù)自旋式的等待(并不放棄 CPU)。
自旋操作是一直讓 CPU 空轉(zhuǎn), 比較浪費 CPU 資源。因此此處的自旋不會一直持續(xù)進行, 而是達到一定的時間、重試次數(shù), 就不再自旋了。也就是所謂的 "自適應(yīng)"

3.重量級鎖

????????如果競爭進一步激烈, 自旋不能快速獲取到鎖狀態(tài),就會膨脹為重量級鎖。此處的重量級鎖就是指用到內(nèi)核提供的 mutex。
????????執(zhí)行加鎖操作, 先進入內(nèi)核態(tài)。在內(nèi)核態(tài)判定當(dāng)前鎖是否已經(jīng)被占用。如果該鎖沒有占用, 則加鎖成功, 并切換回用戶態(tài)。如果該鎖被占用,則加鎖失敗。 此時線程進入鎖的等待隊列、掛起。 等待被操作系統(tǒng)喚醒。經(jīng)歷了一系列的操作, 這個鎖被其他線程釋放了, 操作系統(tǒng)也想起了這個掛起的線程,于是喚醒。這個線程, 嘗試重新獲取鎖。

(3)優(yōu)化操作

1.鎖消除

編譯器+JVM 判斷鎖是否可消除。 如果可以, 就直接消除。

鎖消除:有些應(yīng)用程序的代碼中, 用到了 synchronized, 但其實沒有在多線程環(huán)境下。 (例如StringBuffer)此時每個 append 的調(diào)用都會涉及加鎖、解鎖。但如果只是在單線程中執(zhí)行這個代碼, 那么這些加鎖解鎖操作是沒有必要的,,白白浪費了一些資源開銷??梢赃M行消除操作。
StringBuffer sb = new StringBuffer();
sb.append("a");
sb.append("b");
sb.append("c");
sb.append("d");

2.鎖粗化

一段邏輯中如果出現(xiàn)多次加鎖解鎖,編譯器 + JVM 會自動進行鎖的粗化。

鎖的粒度: 粗和細

????????實際開發(fā)過程中,使用細粒度鎖,是期望釋放鎖的時候其他線程能使用鎖。但是實際上可能并沒有其他線程來搶占這個鎖。這種情況 JVM 就會自動把鎖粗化, 避免頻繁申請釋放鎖。例如給下屬交代工作任務(wù):方式一:打電話,交代任務(wù)1, 掛電話。打電話,交代任務(wù)2,掛電話。打電話, 交代任務(wù)3, 掛電話。方式二:打電話,交代任務(wù)1,任務(wù)2,任務(wù)3,掛電話。顯然,方式二是更高效的方案。這就是鎖粗化的一個過程。

四、synchronized和volatile的區(qū)別

? ? ? ? synchronized和volatile都是Java關(guān)鍵字,并且都是解決線程安全的

?的方式,所以在面試的時候經(jīng)常會被放到一起問。

? ? ? ? 兩者其實并沒有聯(lián)系。

? ? ? ? synchronized:

? ? ? ? 1.通過加鎖、解鎖的方式,把一堆代碼綁在一起,來保證原子性。

? ? ? ? 2.通過加鎖、解鎖的方式,?來保證內(nèi)存可見性。

? ? ? ? 3.對指令重排序有一定約束。

? ? ? ? volatile:

? ? ? ? 1.不能保證原子性。

? ? ? ? 2.保證內(nèi)存可見性。

? ? ? ? 3.禁止指令重排序。? ? ? ?

? ? ? ?雖然synchronized在大多數(shù)情況下,都可以保證線程安全的。但是也不能在任何情況下都用synchronized的。synchronized是要付出一定代價的。synchronized是通過加鎖、解鎖的方式來保證的。所以,其他線程搶不到鎖的時候,線程就會阻塞。線程就會放棄CPU,放棄之后,被重新調(diào)用的時間是不確定的。當(dāng)使用synchronized就一定程度上放棄了高性能。使用volatile不會造成線程阻塞,但對性能也有一定影響,不過沒有synchronized影響大。

? ? ? ? 使用多線程是為了提高效率。使用synchronized,就代表放棄了一定效率。這兩者需要平衡。? ? ??


java synchronized特性,JavaEE,java,java-ee,開發(fā)語言,jvm,面試

?

?

到了這里,關(guān)于【JavaEE】Java中復(fù)雜的Synchronized關(guān)鍵字的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 并發(fā)——synchronized 關(guān)鍵字

    并發(fā)——synchronized 關(guān)鍵字

    synchronized 解決的是多個線程之間訪問資源的同步性, synchronized 可以保證被它修飾的方法或者代碼塊在任意時刻只能有一個線程執(zhí)行。 另外,在 Java 早期版本中, synchronized 屬于 重量級鎖 ,效率低下。 為什么呢? 因為監(jiān)視器鎖(monitor)是依賴于底層的操作系

    2024年02月13日
    瀏覽(21)
  • 【Synchronized關(guān)鍵字】

    Synchronized是Java中的,它用于控制多線程之間的訪問,保證同一時刻只有一個線程可以執(zhí)行被鎖定的代碼塊或方法。在多線程編程中,Synchronized是一種非常重要的機制,它可以避免多個線程同時訪問共享資源而產(chǎn)生數(shù)據(jù)不一致性的問題。 Synchronized有兩種使用方式:對代

    2024年02月08日
    瀏覽(55)
  • 線程中synchronized關(guān)鍵字和lock接口的異同

    線程中synchronized關(guān)鍵字和lock接口的異同

    一、synchronized 1.可以用來修飾代碼塊? 2.可以用在方法上 修飾同步方法 while (true) { try { Thread.sleep(200); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(sellTicket()) { break; } } 二、lock接口? 1.用此接口要用? ? ?ReentrantLock l = new ReentrantLock();? ? ?

    2024年02月08日
    瀏覽(18)
  • 線程的狀態(tài),多線程帶來的風(fēng)險,synchronized關(guān)鍵字及死鎖問題

    線程的狀態(tài),多線程帶來的風(fēng)險,synchronized關(guān)鍵字及死鎖問題

    目錄 狀態(tài)? 線程的意義 多線程帶來的風(fēng)險——線程安全? 線程安全的概念 線程不安全的原因 搶占式執(zhí)行,隨機性調(diào)度 修改共享數(shù)據(jù) 原子性-加?? 可見性 指令重排序 解決線程不安全問題(學(xué)完線程再總結(jié)) synchronized——監(jiān)視器鎖monitor lock?編輯? ?互斥 使用示例

    2024年02月06日
    瀏覽(40)
  • [JAVAee]volatile關(guān)鍵字

    [JAVAee]volatile關(guān)鍵字

    目錄 1.volatile的特性 ①保持線程可見性 2.volatile注意事項及適用場景 ①注意事項 ②適用場景 volatile,譯為\\\"易變的\\\". 對此我們就可以這樣理解,對于被volatile修飾的變量的數(shù)值,是容易變化的. 在之前的線程安全文章中,我們有講解過\\\"可見性\\\",對于線程間的這個特性可能會導(dǎo)致:線程

    2024年02月16日
    瀏覽(23)
  • 《吊打面試官系列》從源碼全面解析 synchronized 關(guān)鍵字的來龍去脈

    《吊打面試官系列》從源碼全面解析 synchronized 關(guān)鍵字的來龍去脈

    ??作者簡介:大家好,我是愛敲代碼的小黃,獨角獸企業(yè)的Java開發(fā)工程師,CSDN博客專家,阿里云專家博主 ??系列專欄:Java設(shè)計模式、數(shù)據(jù)結(jié)構(gòu)和算法、Kafka從入門到成神、Kafka從成神到升仙、Spring從成神到升仙系列 ??如果感覺博主的文章還不錯的話,請??三連支持??一

    2023年04月16日
    瀏覽(14)
  • Java ---一些關(guān)鍵字

    ?①含義: this:當(dāng)前對象 在構(gòu)造器和非靜態(tài)代碼塊中,表示正在new的對象 在實例方法中,表示調(diào)用當(dāng)前方法的對象 ②this用法: this.成員變量:表示當(dāng)前對象的某個成員變量,而不是局部變量 this.成員方法:表示當(dāng)前對象的某個成員方法,完全可以省略this. this()或this(實參列

    2023年04月09日
    瀏覽(24)
  • 【Java入門】final關(guān)鍵字、static關(guān)鍵字、內(nèi)部類的認識

    前言 : final是Java中的一個修飾符,用于表示某個變量、方法或者類不能被修改。final可以用于修飾類、方法和變量(局部變量,成員變量)。被final所修飾的類不能被繼承,被final所修飾的方法不能被重寫,被final所修飾的變量,不能被重新賦值 。 static是Java中的一

    2024年02月11日
    瀏覽(93)
  • 關(guān)于哪些java關(guān)鍵字

    放有道筆記里面東西太多,整理整理放出來 1: 關(guān)于static: 》在不實例化對象的情況下訪問變量或者調(diào)用方法,常用的如各種工具類,無狀態(tài)且無需實例化對象,直接調(diào)用。 》static代碼塊,常用來在加載class的時候就初始化且只有一次:配置文件加載,keystore/truststore初始化。

    2024年02月03日
    瀏覽(26)
  • JAVA volatile 關(guān)鍵字

    volatile 是JAVA虛擬機提供的輕量級的同步機制,有三大特性 1、保證可見性? 2、不保證原子性? 3、禁止指令重排 JMM? JAVA內(nèi)存模型本身是一種抽象的概念并不真實存在 它描述的是一組規(guī)則或規(guī)范,提供這組規(guī)范定義了程序中各個變量(包括實例變量、靜態(tài)變量)的訪問方式。

    2024年02月13日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包