最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 深入淺出分析Synchronized原理與Callable接口

 更新時間:2022年03月23日 16:03:30   作者:/少司命  
Synchronized關(guān)鍵字解決的是多個線程之間訪問資源的同步性,synchronized關(guān)鍵字可以保證被它修飾的方法或者代碼塊在任意時刻只能有一個線程執(zhí)行,Runnable是執(zhí)行工作的獨立任務(wù),但是不返回任何值。如果我們希望任務(wù)完成之后有返回值,可以實現(xiàn)Callable接口

一、基本特點

1. 開始時是樂觀鎖, 如果鎖沖突頻繁, 就轉(zhuǎn)換為悲觀鎖.

2. 開始是輕量級鎖實現(xiàn), 如果鎖被持有的時間較長, 就轉(zhuǎn)換成重量級鎖.

3. 實現(xiàn)輕量級鎖的時候大概率用到的自旋鎖策略

4. 是一種不公平鎖

5. 是一種可重入鎖

6. 不是讀寫鎖

二、加鎖工作過程

JVM 將 synchronized 鎖分為 無鎖、偏向鎖、輕量級鎖、重量級鎖狀態(tài)。會根據(jù)情況,進行依次升級。

偏向鎖

假設(shè)男主是一個鎖, 女主是一個線程. 如果只有這一個線程來使用這個鎖, 那么男主女主即使不領(lǐng)證 結(jié)婚(避免了高成本操作), 也可以一直幸福的生活下去. 但是女配出現(xiàn)了, 也嘗試競爭男主, 此時不管領(lǐng)證結(jié)婚這個操作成本多高, 女主也勢必要把這個動作 完成了, 讓女配死心

偏向鎖不是真的 "加鎖", 只是給對象頭中做一個 "偏向鎖的標(biāo)記", 記錄這個鎖屬于哪個線程. 如果后續(xù)沒有其他線程來競爭該鎖, 那么就不用進行其他同步操作了(避免了加鎖解鎖的開銷) 如果后續(xù)有其他線程來競爭該鎖(剛才已經(jīng)在鎖對象中記錄了當(dāng)前鎖屬于哪個線程了, 很容易識別 當(dāng)前申請鎖的線程是不是之前記錄的線程), 那就取消原來的偏向鎖狀態(tài), 進入一般的輕量級鎖狀態(tài)

偏向鎖本質(zhì)上相當(dāng)于 "延遲加鎖" . 能不加鎖就不加鎖, 盡量來避免不必要的加鎖開銷. 但是該做的標(biāo)記還是得做的, 否則無法區(qū)分何時需要真正加鎖

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

輕量級鎖

隨著其他線程進入競爭, 偏向鎖狀態(tài)被消除, 進入輕量級鎖狀態(tài)(自適應(yīng)的自旋鎖). 此處的輕量級鎖就是通過 CAS 來實現(xiàn).

通過 CAS 檢查并更新一塊內(nèi)存 (比如 null => 該線程引用)

如果更新成功, 則認為加鎖成功

如果更新失敗, 則認為鎖被占用, 繼續(xù)自旋式的等待(并不放棄 CPU).

自旋操作是一直讓 CPU 空轉(zhuǎn), 比較浪費 CPU 資源. 因此此處的自旋不會一直持續(xù)進行, 而是達到一定的時間/重試次數(shù), 就不再自旋了. 也就是所謂的 "自適應(yīng)"

重量級鎖

如果競爭進一步激烈, 自旋不能快速獲取到鎖狀態(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)也想起了這個掛起的線程, 于是喚醒 這個線程, 嘗試重新獲取鎖

三、其他的優(yōu)化操作

鎖消除

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

有些應(yīng)用程序的代碼中, 用到了 synchronized, 但其實沒有在多線程環(huán)境下. (例如 StringBuffer)

StringBuffer sb = new StringBuffer();
sb.append("a");
sb.append("b");
sb.append("c");
sb.append("d");

此時每個 append 的調(diào)用都會涉及加鎖和解鎖. 但如果只是在單線程中執(zhí)行這個代碼, 那么這些加 鎖解鎖操作是沒有必要的, 白白浪費了一些資源開銷.

鎖粗化

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

領(lǐng)導(dǎo), 給下屬交代工作任務(wù)

方式一:

打電話, 交代任務(wù)1, 掛電話.

打電話, 交代任務(wù)2, 掛電話.

打電話, 交代任務(wù)3, 掛電話

方式二:

打電話, 交代任務(wù)1, 任務(wù)2, 任務(wù)3, 掛電話

四、Callable 接口

Callable 是什么

Callable 是一個 interface . 相當(dāng)于把線程封裝了一個 "返回值". 方便程序猿借助多線程的方式計算 結(jié)果.

Callable 和 Runnable 相對, 都是描述一個 "任務(wù)". Callable 描述的是帶有返回值的任務(wù), Runnable 描述的是不帶返回值的任務(wù).Callable 通常需要搭配 FutureTask 來使用. FutureTask 用來保存 Callable 的返回結(jié)果. 因為 Callable 往往是在另一個線程中執(zhí)行的, 啥時候執(zhí)行完并不確定. FutureTask 就可以負責(zé)這個等待結(jié)果出來的工作.

代碼示例: 創(chuàng)建線程計算 1 + 2 + 3 + ... + 1000, 不使用 Callable 版本

public class Text {
 
    static class Result{
        public int sum = 0;
        public Object locker = new Object();
    }
 
    public static void main(String[] args) throws InterruptedException {
        Result result = new Result();
 
        Thread t = new Thread(){
            @Override
            public void run() {
                int sum = 0;
                for (int i = 0; i <=10000; i++){
                    sum += i;
                }
                result.sum = sum;
 
                synchronized (result.locker){
                    result.locker.notify();
                }
            }
        };
        t.start();
        synchronized (result.locker){
            while (result.sum == 0){
                result.locker.wait();
            }
        }
        System.out.println(result.sum);
    }
}

代碼示例: 創(chuàng)建線程計算 1 + 2 + 3 + ... + 1000, 使用 Callable 版本

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
 
public class Text1 {
 
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int sum = 0;
                for (int i = 0; i <=1000; i++){
                    sum += i;
                }
                return sum;
            }
        };
        //由于Thread不能直接傳一個callable實例,就需要一個輔助類來包裝
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        Thread t = new Thread(futureTask);
        t.start();
        //嘗試在主線程獲取結(jié)果
        //如果FutureTask中的結(jié)果還沒生成。此時就會阻塞等待
        //一直等到最終的線程把這個結(jié)果算出來,get返回
        Integer result = futureTask.get();
        System.out.println(result);
    }
}

到此這篇關(guān)于Java 深入淺出分析Synchronized原理與Callable接口的文章就介紹到這了,更多相關(guān)Java Synchronized 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • centos7如何通過systemctl啟動springboot服務(wù)代替java -jar方式啟動

    centos7如何通過systemctl啟動springboot服務(wù)代替java -jar方式啟動

    這篇文章主要介紹了centos7如何通過systemctl啟動springboot服務(wù)代替java -jar方式啟動,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-01-01
  • springboot集成spring cache緩存示例代碼

    springboot集成spring cache緩存示例代碼

    本篇文章主要介紹了springboot集成spring cache示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • Java 中如何使用 JavaFx 庫標(biāo)注文本顏色

    Java 中如何使用 JavaFx 庫標(biāo)注文本顏色

    這篇文章主要介紹了在 Java 中用 JavaFx 庫標(biāo)注文本顏色,在本文中,我們將了解如何更改標(biāo)簽的文本顏色,并且我們還將看到一個必要的示例和適當(dāng)?shù)慕忉?,以便更容易理解該主題,需要的朋友可以參考下
    2023-05-05
  • 淺談java多態(tài)的實現(xiàn)主要體現(xiàn)在哪些方面

    淺談java多態(tài)的實現(xiàn)主要體現(xiàn)在哪些方面

    下面小編就為大家?guī)硪黄獪\談java多態(tài)的實現(xiàn)主要體現(xiàn)在哪些方面。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • java圖形界面編程實戰(zhàn)代碼

    java圖形界面編程實戰(zhàn)代碼

    這篇文章主要介紹了java圖形界面編程實戰(zhàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-07-07
  • MyBatis中XML 映射文件中常見的標(biāo)簽說明

    MyBatis中XML 映射文件中常見的標(biāo)簽說明

    這篇文章主要介紹了MyBatis中XML 映射文件中常見的標(biāo)簽說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Swagger-boostrap-ui如何配置用戶名密碼訪問

    Swagger-boostrap-ui如何配置用戶名密碼訪問

    這篇文章主要介紹了Swagger-boostrap-ui如何配置用戶名密碼訪問,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Java RPC框架如何實現(xiàn)客戶端限流配置

    Java RPC框架如何實現(xiàn)客戶端限流配置

    這篇文章主要介紹了Java RPC框架如何實現(xiàn)客戶端限流配置,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • Java實現(xiàn)彈窗效果的基本操作(2)

    Java實現(xiàn)彈窗效果的基本操作(2)

    這篇文章主要為大家詳細介紹了Java實現(xiàn)彈窗效果的基本操作第二篇,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • Java基本數(shù)據(jù)類型與類型轉(zhuǎn)換實例分析

    Java基本數(shù)據(jù)類型與類型轉(zhuǎn)換實例分析

    這篇文章主要介紹了Java基本數(shù)據(jù)類型與類型轉(zhuǎn)換,結(jié)合實例形式分析了Java基本數(shù)據(jù)類型分類、用法,類型轉(zhuǎn)換及相關(guān)操作注意事項,需要的朋友可以參考下
    2020-04-04

最新評論

洛南县| 玉田县| 客服| 洪雅县| 昂仁县| 平遥县| 永顺县| 抚顺市| 奉贤区| 大余县| 高淳县| 天峨县| 桦南县| 麻江县| 盐城市| 尼勒克县| 喀什市| 井冈山市| 蛟河市| 乌兰县| 衢州市| 神木县| 长葛市| 清丰县| 宁海县| 江阴市| 台中县| 浦东新区| 丰城市| 霍林郭勒市| 武宁县| 柳江县| 漾濞| 旬阳县| 江北区| 勃利县| 隆昌县| 雅江县| 赣州市| 泸西县| 衡山县|