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

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

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

并發(fā)——synchronized 關(guān)鍵字,java筆記整理,java

1.說一說自己對于 synchronized 關(guān)鍵字的了解

synchronized 關(guān)鍵字解決的是多個線程之間訪問資源的同步性,synchronized關(guān)鍵字可以保證被它修飾的方法或者代碼塊在任意時刻只能有一個線程執(zhí)行。

另外,在 Java 早期版本中,synchronized 屬于 重量級鎖,效率低下。

為什么呢?

因為監(jiān)視器鎖(monitor)是依賴于底層的操作系統(tǒng)的 Mutex Lock 來實現(xiàn)的,Java 的線程是映射到操作系統(tǒng)的原生線程之上的。如果要掛起或者喚醒一個線程,都需要操作系統(tǒng)幫忙完成,而操作系統(tǒng)實現(xiàn)線程之間的切換時需要從用戶態(tài)轉(zhuǎn)換到內(nèi)核態(tài),這個狀態(tài)之間的轉(zhuǎn)換需要相對比較長的時間,時間成本相對較高。

慶幸的是在 Java 6 之后 Java 官方對從 JVM 層面對 synchronized 較大優(yōu)化,所以現(xiàn)在的 synchronized 鎖效率也優(yōu)化得很不錯了。JDK1.6 對鎖的實現(xiàn)引入了大量的優(yōu)化,如自旋鎖、適應(yīng)性自旋鎖、鎖消除、鎖粗化、偏向鎖、輕量級鎖等技術(shù)來減少鎖操作的開銷。

所以,你會發(fā)現(xiàn)目前的話,不論是各種開源框架還是 JDK 源碼都大量使用了 synchronized 關(guān)鍵字。

2. 說說自己是怎么使用 synchronized 關(guān)鍵字

synchronized 關(guān)鍵字最主要的三種使用方式:

1.修飾實例方法: 作用于當前對象實例加鎖,進入同步代碼前要獲得 當前對象實例的鎖

synchronized void method() {
  //業(yè)務(wù)代碼
}

2.修飾靜態(tài)方法: 也就是給當前類加鎖,會作用于類的所有對象實例 ,進入同步代碼前要獲得 當前 class 的鎖。因為靜態(tài)成員不屬于任何一個實例對象,是類成員( static 表明這是該類的一個靜態(tài)資源,不管 new 了多少個對象,只有一份)。所以,如果一個線程 A 調(diào)用一個實例對象的非靜態(tài) synchronized 方法,而線程 B 需要調(diào)用這個實例對象所屬類的靜態(tài) synchronized 方法,是允許的,不會發(fā)生互斥現(xiàn)象,因為訪問靜態(tài) synchronized 方法占用的鎖是當前類的鎖,而訪問非靜態(tài) synchronized 方法占用的鎖是當前實例對象鎖。

synchronized void staic method() {
  //業(yè)務(wù)代碼
}

3.修飾代碼塊 :指定加鎖對象,對給定對象/類加鎖。synchronized(this|object) 表示進入同步代碼庫前要獲得給定對象的鎖。synchronized(類.class) 表示進入同步代碼前要獲得 當前 class 的鎖

synchronized(this) {
  //業(yè)務(wù)代碼
}

總結(jié):

  • synchronized 關(guān)鍵字加到 static 靜態(tài)方法和 synchronized(class) 代碼塊上都是是給 Class 類上鎖。
  • synchronized 關(guān)鍵字加到實例方法上是給對象實例上鎖。
  • 盡量不要使用 synchronized(String a) 因為 JVM 中,字符串常量池具有緩存功能!

下面我以一個常見的面試題為例講解一下 synchronized 關(guān)鍵字的具體使用。

面試中面試官經(jīng)常會說:“單例模式了解嗎?來給我手寫一下!給我解釋一下雙重檢驗鎖方式實現(xiàn)單例模式的原理唄!”

雙重校驗鎖實現(xiàn)對象單例(線程安全)

public class Singleton {

    private volatile static Singleton uniqueInstance;

    private Singleton() {
    }

    public  static Singleton getUniqueInstance() {
       //先判斷對象是否已經(jīng)實例過,沒有實例化過才進入加鎖代碼
        if (uniqueInstance == null) {
            //類對象加鎖
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

另外,需要注意 uniqueInstance 采用 volatile 關(guān)鍵字修飾也是很有必要。

uniqueInstance 采用 volatile 關(guān)鍵字修飾也是很有必要的, uniqueInstance = new Singleton(); 這段代碼其實是分為三步執(zhí)行:

  1. uniqueInstance 分配內(nèi)存空間
  2. 初始化 uniqueInstance
  3. uniqueInstance 指向分配的內(nèi)存地址

但是由于 JVM 具有指令重排的特性,執(zhí)行順序有可能變成 1->3->2。指令重排在單線程環(huán)境下不會出現(xiàn)問題,但是在多線程環(huán)境下會導(dǎo)致一個線程獲得還沒有初始化的實例。例如,線程 T1 執(zhí)行了 1 和 3,此時 T2 調(diào)用 getUniqueInstance() 后發(fā)現(xiàn) uniqueInstance 不為空,因此返回 uniqueInstance,但此時 uniqueInstance 還未被初始化。

使用 volatile 可以禁止 JVM 的指令重排,保證在多線程環(huán)境下也能正常運行。

3. 構(gòu)造方法可以使用 synchronized 關(guān)鍵字修飾么?

先說結(jié)論:構(gòu)造方法不能使用 synchronized 關(guān)鍵字修飾。

構(gòu)造方法本身就屬于線程安全的,不存在同步的構(gòu)造方法一說。

4. 講一下 synchronized 關(guān)鍵字的底層原理

synchronized 關(guān)鍵字底層原理屬于 JVM 層面。

4.1. synchronized 同步語句塊的情況

public class SynchronizedDemo {
	public void method() {
		synchronized (this) {
			System.out.println("synchronized 代碼塊");
		}
	}
}

通過 JDK 自帶的 javap 命令查看 SynchronizedDemo 類的相關(guān)字節(jié)碼信息:首先切換到類的對應(yīng)目錄執(zhí)行 javac SynchronizedDemo.java 命令生成編譯后的 .class 文件,然后執(zhí)行javap -c -s -v -l SynchronizedDemo.class。

并發(fā)——synchronized 關(guān)鍵字,java筆記整理,java

從上面我們可以看出:

synchronized 同步語句塊的實現(xiàn)使用的是 monitorentermonitorexit 指令,其中 monitorenter 指令指向同步代碼塊的開始位置,monitorexit 指令則指明同步代碼塊的結(jié)束位置。

當執(zhí)行 monitorenter 指令時,線程試圖獲取鎖也就是獲取 對象監(jiān)視器 monitor 的持有權(quán)。

在 Java 虛擬機(HotSpot)中,Monitor 是基于 C++實現(xiàn)的,由ObjectMonitor實現(xiàn)的。每個對象中都內(nèi)置了一個 ObjectMonitor對象。

另外,wait/notify等方法也依賴于monitor對象,這就是為什么只有在同步的塊或者方法中才能調(diào)用wait/notify等方法,否則會拋出java.lang.IllegalMonitorStateException的異常的原因。

在執(zhí)行monitorenter時,會嘗試獲取對象的鎖,如果鎖的計數(shù)器為 0 則表示鎖可以被獲取,獲取后將鎖計數(shù)器設(shè)為 1 也就是加 1。

在執(zhí)行 monitorexit 指令后,將鎖計數(shù)器設(shè)為 0,表明鎖被釋放。如果獲取對象鎖失敗,那當前線程就要阻塞等待,直到鎖被另外一個線程釋放為止。

4.2. synchronized 修飾方法的的情況

public class SynchronizedDemo2 {
	public synchronized void method() {
		System.out.println("synchronized 方法");
	}
}

并發(fā)——synchronized 關(guān)鍵字,java筆記整理,java

synchronized 修飾的方法并沒有 monitorenter 指令和 monitorexit 指令,取得代之的確實是 ACC_SYNCHRONIZED 標識,該標識指明了該方法是一個同步方法。JVM 通過該 ACC_SYNCHRONIZED 訪問標志來辨別一個方法是否聲明為同步方法,從而執(zhí)行相應(yīng)的同步調(diào)用。

4.3.總結(jié)

synchronized 同步語句塊的實現(xiàn)使用的是 monitorentermonitorexit 指令,其中 monitorenter 指令指向同步代碼塊的開始位置,monitorexit 指令則指明同步代碼塊的結(jié)束位置。

synchronized 修飾的方法并沒有 monitorenter 指令和 monitorexit 指令,取得代之的確實是 ACC_SYNCHRONIZED 標識,該標識指明了該方法是一個同步方法。

不過兩者的本質(zhì)都是對對象監(jiān)視器 monitor 的獲取。

5. 說說 JDK1.6 之后的 synchronized 關(guān)鍵字底層做了哪些優(yōu)化,可以詳細介紹一下這些優(yōu)化嗎

JDK1.6 對鎖的實現(xiàn)引入了大量的優(yōu)化,如偏向鎖、輕量級鎖、自旋鎖、適應(yīng)性自旋鎖、鎖消除、鎖粗化等技術(shù)來減少鎖操作的開銷。

鎖主要存在四種狀態(tài),依次是:無鎖狀態(tài)、偏向鎖狀態(tài)、輕量級鎖狀態(tài)、重量級鎖狀態(tài),他們會隨著競爭的激烈而逐漸升級。注意鎖可以升級不可降級,這種策略是為了提高獲得鎖和釋放鎖的效率。

關(guān)于這幾種優(yōu)化的詳細信息可以查看下面這篇文章:Java6 及以上版本對 synchronized 的優(yōu)化

6. 談?wù)?synchronized 和 ReentrantLock 的區(qū)別

6.1. 兩者都是可重入鎖

“可重入鎖” 指的是自己可以再次獲取自己的內(nèi)部鎖。比如一個線程獲得了某個對象的鎖,此時這個對象鎖還沒有釋放,當其再次想要獲取這個對象的鎖的時候還是可以獲取的,如果不可鎖重入的話,就會造成死鎖。同一個線程每次獲取鎖,鎖的計數(shù)器都自增 1,所以要等到鎖的計數(shù)器下降為 0 時才能釋放鎖。

6.2.synchronized 依賴于 JVM 而 ReentrantLock 依賴于 API

synchronized 是依賴于 JVM 實現(xiàn)的,前面我們也講到了 虛擬機團隊在 JDK1.6 為 synchronized 關(guān)鍵字進行了很多優(yōu)化,但是這些優(yōu)化都是在虛擬機層面實現(xiàn)的,并沒有直接暴露給我們。ReentrantLock 是 JDK 層面實現(xiàn)的(也就是 API 層面,需要 lock() 和 unlock() 方法配合 try/finally 語句塊來完成),所以我們可以通過查看它的源代碼,來看它是如何實現(xiàn)的。

6.3.ReentrantLock 比 synchronized 增加了一些高級功能

相比synchronized,ReentrantLock增加了一些高級功能。主要來說主要有三點:

  • 等待可中斷 : ReentrantLock提供了一種能夠中斷等待鎖的線程的機制,通過 lock.lockInterruptibly() 來實現(xiàn)這個機制。也就是說正在等待的線程可以選擇放棄等待,改為處理其他事情。
  • 可實現(xiàn)公平鎖 : ReentrantLock可以指定是公平鎖還是非公平鎖。而synchronized只能是非公平鎖。所謂的公平鎖就是先等待的線程先獲得鎖。ReentrantLock默認情況是非公平的,可以通過 ReentrantLock類的ReentrantLock(boolean fair)構(gòu)造方法來制定是否是公平的。
  • 可實現(xiàn)選擇性通知(鎖可以綁定多個條件): synchronized關(guān)鍵字與wait()notify()/notifyAll()方法相結(jié)合可以實現(xiàn)等待/通知機制。ReentrantLock類當然也可以實現(xiàn),但是需要借助于Condition接口與newCondition()方法。

Condition是 JDK1.5 之后才有的,它具有很好的靈活性,比如可以實現(xiàn)多路通知功能也就是在一個Lock對象中可以創(chuàng)建多個Condition實例(即對象監(jiān)視器),線程對象可以注冊在指定的Condition中,從而可以有選擇性的進行線程通知,在調(diào)度線程上更加靈活。 在使用notify()/notifyAll()方法進行通知時,被通知的線程是由 JVM 選擇的,用ReentrantLock類結(jié)合Condition實例可以實現(xiàn)“選擇性通知” ,這個功能非常重要,而且是 Condition 接口默認提供的。而synchronized關(guān)鍵字就相當于整個 Lock 對象中只有一個Condition實例,所有的線程都注冊在它一個身上。如果執(zhí)行notifyAll()方法的話就會通知所有處于等待狀態(tài)的線程這樣會造成很大的效率問題,而Condition實例的signalAll()方法 只會喚醒注冊在該Condition實例中的所有等待線程。

如果你想使用上述功能,那么選擇 ReentrantLock 是一個不錯的選擇。性能已不是選擇標準文章來源地址http://www.zghlxwxcb.cn/news/detail-635682.html

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

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

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

相關(guān)文章

  • Java 八股文面試過程系列之synchronized關(guān)鍵字

    本文通過一場虛擬的面試對話,詳細解析了Java中的synchronized關(guān)鍵字。從基本用法到底層實現(xiàn)原理,再到性能優(yōu)化策略,全面提升您對同步機制的理解。

    2024年02月07日
    瀏覽(37)
  • 【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)
  • 不可不看的Java基礎(chǔ)知識整理,注釋、關(guān)鍵字、運算符

    不可不看的Java基礎(chǔ)知識整理,注釋、關(guān)鍵字、運算符

    萬丈高樓平地起,要想學(xué)好漢語首先學(xué)拼音,想學(xué)好英語首先學(xué)26個字母,對于編程語言來說,一樣的道理,要想學(xué)好必須先掌握其基礎(chǔ)語法和知識,今天我們就來嘮一嘮Java語言中那些出現(xiàn)頻率極高,又很基礎(chǔ)的知識點吧! 注釋的作用:撥云見日! 在日常的工作中,總會遇

    2024年01月16日
    瀏覽(23)
  • 線程的狀態(tài),多線程帶來的風險,synchronized關(guān)鍵字及死鎖問題

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

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

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

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

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

    2023年04月16日
    瀏覽(15)
  • final關(guān)鍵字--java學(xué)習筆記

    final關(guān)鍵字--java學(xué)習筆記

    final是最終的意思,可以修飾類、方法、變量 修飾類:該類被稱為最終類,特點是不能被繼承了 修飾方法:該方法被稱為最終方法,特點是不能被重寫了 修飾變量:該變量只能被賦值一次 就相當于給類、方法、變量做了一個絕育手術(shù)? 示例: final修飾類: final修飾方

    2024年01月18日
    瀏覽(298)
  • 線程中并發(fā)安全問題(Sychronized關(guān)鍵字的底層原理)

    線程中并發(fā)安全問題(Sychronized關(guān)鍵字的底層原理)

    Sychronized的底層原理 ? sychronized 對象鎖采用互斥方式讓同一時刻至多只有一個線程能持有對象鎖,其他線程想獲取這個對象鎖只能被阻塞。 Monitor Sychronized的底層實現(xiàn)Monitor。 WaitSet:關(guān)聯(lián)調(diào)用了wait方法的線程,用于存儲處于等待狀態(tài)的線程。 EntryList:關(guān)聯(lián)了沒有獲得

    2024年02月16日
    瀏覽(22)
  • 【Java入門】final關(guān)鍵字、static關(guān)鍵字、內(nèi)部類的認識

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

    2024年02月11日
    瀏覽(93)
  • Java面向?qū)ο蟆鄳B(tài)、Object類、instanceof關(guān)鍵字以及final關(guān)鍵字

    Java面向?qū)ο蟆鄳B(tài)、Object類、instanceof關(guān)鍵字以及final關(guān)鍵字

    總之,多態(tài)是面向?qū)ο缶幊讨幸粋€非常重要的概念,通過它可以實現(xiàn)統(tǒng)一的接口來操作不同的對象,提高代碼的可讀性和可維護性。在實際編程中,多態(tài)性的使用可以使代碼更加靈活和擴展性更強。方法重寫是實現(xiàn)多態(tài)的基礎(chǔ)。 重寫如下所示 關(guān)于hashCode方法的重寫: 重寫t

    2024年02月12日
    瀏覽(114)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包