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

Java線程安全狀態(tài)專題解析

 更新時(shí)間:2022年03月02日 14:27:18   作者:/少司命  
線程安全是多線程編程時(shí)的計(jì)算機(jī)程序代碼中的一個概念。在擁有共享數(shù)據(jù)的多條線程并行執(zhí)行的程序中,線程安全的代碼會通過同步機(jī)制保證各個線程都可以正常且正確的執(zhí)行,不會出現(xiàn)數(shù)據(jù)污染等意外情況

一、觀察線程的所有狀態(tài)

線程的狀態(tài)是一個枚舉類型 Thread.State

 public static void main(String[] args) {
        for (Thread.State state : Thread.State.values()){
            System.out.println(state);
        }
    }

NEW: 安排了工作, 還未開始行動

RUNNABLE: 可工作的. 又可以分成正在工作中和即將開始工作.就緒狀態(tài)

BLOCKED: 這幾個都表示排隊(duì)等著其他事情

WAITING: 這幾個都表示排隊(duì)等著其他事情

TIMED_WAITING: 這幾個都表示排隊(duì)等著其他事情

TERMINATED: 工作完成了.

二、線程狀態(tài)和狀態(tài)轉(zhuǎn)移的意義

NEW:Thread對象有了,但是PCB還沒有

RUNNABLE:線程正在CPU上執(zhí)行或者即將到CPU上執(zhí)行(PCB在就緒隊(duì)列中,隨時(shí)可能被調(diào)度到)

WAITING:wait方法導(dǎo)致

TIMED_WAITING:sleep方法導(dǎo)致

BLOCKED:等待鎖導(dǎo)致

TERMINATED:對象還在,但PCB已經(jīng)沒了

public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 100_00; i++){
 
                }
            }
        };
        System.out.println("線程啟動前:" + t.getState());
 
        t.start();
        while (t.isAlive()){
            System.out.println("線程運(yùn)行中:" + t.getState());
        }
        System.out.println("線程結(jié)束后:" + t.getState());
    }

三、多線程帶來的風(fēng)險(xiǎn)

線程不安全的原因

①線程是搶占式執(zhí)行的

線程不安全的萬惡之源,線程之間的調(diào)度完全由內(nèi)核負(fù)責(zé),用戶代碼中感知不到,也無法控制。線程之間誰先執(zhí)行,誰后執(zhí)行,誰執(zhí)行到哪里從CPU上下來,這樣的過程用戶無法控制也無法感知到的。

②自增操作不是原子的

每次++都能拆成三個步驟

? ? ? ? 把內(nèi)存中的數(shù)據(jù)讀取到CPU中

? ? ? ? 把CPU中的數(shù)據(jù)+1

? ? ? ? 把計(jì)算的數(shù)據(jù)寫回內(nèi)存中

如果兩個線程串行執(zhí)行,此時(shí)計(jì)算結(jié)果為2。

如果兩個線程并行執(zhí)行,線程1進(jìn)行++操作到一半的時(shí)候,線程也進(jìn)行了++操作,此時(shí)自增兩次,但結(jié)果為1。

必須保證線程1save結(jié)束了,線程2再load,此時(shí)計(jì)算結(jié)果才正確

③多個線程嘗試修改同一個變量

如果是一個線程修改一個變量,線程安全

如果多個線程讀取同一個變量,線程安全

如果多個線程修改不同的變量。線程安全

④內(nèi)存可見性導(dǎo)致線程安全問題

⑤指令重排序

Java的編譯器在編譯代碼時(shí),會對指令進(jìn)行優(yōu)化,調(diào)整指令的先后順序,保證原有的邏輯不變的情況下,提高程序的運(yùn)行效率

四,解決線程安全問題

鎖-synchronized

未加鎖

static class Counter{
        public int count = 0;
 
         public void increase(){
            count++;
        }
    }
 
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Thread t1 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50000; i++){
                    counter.increase();
                }
            }
        };
        Thread t2 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50000; i++){
                    counter.increase();
                }
            }
        };
        t1.start();
        t2.start();
        t1.join();
        t2.join();
 
        System.out.println(counter.count);
    }

?已加鎖

static class Counter{
        public int count = 0;
 
        synchronized public void increase(){
            count++;
        }
    }
 
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Thread t1 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50000; i++){
                    counter.increase();
                }
            }
        };
        Thread t2 = new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50000; i++){
                    counter.increase();
                }
            }
        };
        t1.start();
        t2.start();
        t1.join();
        t2.join();
 
        System.out.println(counter.count);
    }

此處的synchronized就是針對counter這個對象來加鎖,進(jìn)入increase方法內(nèi)部,就把加鎖狀態(tài)設(shè)為ture,increase方法退出之后,就把加鎖狀態(tài)設(shè)為false,如果某個線程已經(jīng)把加鎖狀態(tài)設(shè)為ture,此處的其他的線程嘗試去加鎖,就會阻塞

synchronized的特性——刷新內(nèi)存

synchronized 的工作過程:

????????1. 獲得互斥鎖

????????2. 從主內(nèi)存拷貝變量的最新副本到工作的內(nèi)存

????????3. 執(zhí)行代碼

????????4. 將更改后的共享變量的值刷新到主內(nèi)存

????????5. 釋放互斥鎖

synchronized的特性——互斥

 public static void main(String[] args) {
        Object locker = new Object();
 
        Thread t1 = new Thread(){
            @Override
            public void run() {
                Scanner scanner = new Scanner(System.in);
                synchronized (locker) {
                    System.out.println("輸入一個整數(shù)");
                    int num = scanner.nextInt();
                    System.out.println("num= " + num);
                }
            }
        };
        t1.start();
 
        Thread t2 = new Thread(){
            @Override
            public void run() {
                while (true){
                    synchronized (locker){
                        System.out.println("線程2獲取到鎖");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };
        t2.start();
    }

一旦線程一獲取到鎖,并且沒有釋放的話,線程2就會一直在鎖這里阻塞等待

 public static void main(String[] args) {
        Object locker1 = new Object();
        Object locker2 = new Object();
 
        Thread t1 = new Thread(){
            @Override
            public void run() {
                Scanner scanner = new Scanner(System.in);
                synchronized (locker1) {
                    System.out.println("輸入一個整數(shù)");
                    int num = scanner.nextInt();
                    System.out.println("num= " + num);
                }
            }
        };
        t1.start();
 
        Thread t2 = new Thread(){
            @Override
            public void run() {
                while (true){
                    synchronized (locker2){
                        System.out.println("線程2獲取到鎖");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };
        t2.start();
    }

?不是同一把鎖,就不回出現(xiàn)競爭,就沒有互斥了。

public static void main(String[] args) {
        Object locker1 = new Object();
        Object locker2 = new Object();
 
        Thread t1 = new Thread(){
            @Override
            public void run() {
                Scanner scanner = new Scanner(System.in);
                synchronized (locker1.getClass()) {
                    System.out.println("輸入一個整數(shù)");
                    int num = scanner.nextInt();
                    System.out.println("num= " + num);
                }
            }
        };
        t1.start();
 
        Thread t2 = new Thread(){
            @Override
            public void run() {
                while (true){
                    synchronized (locker2.getClass()){
                        System.out.println("線程2獲取到鎖");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };
        t2.start();
    }

這個代碼中,兩個線程都在針對locker1和locker2的類對象進(jìn)行競爭,此處的locker1和locker2的類型都是Object,對應(yīng)的對象都是相同的對象。?

到此這篇關(guān)于Java線程安全狀態(tài)專題解析的文章就介紹到這了,更多相關(guān)Java 線程安全內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java訪問者模式實(shí)現(xiàn)優(yōu)雅的對象結(jié)構(gòu)處理

    Java訪問者模式實(shí)現(xiàn)優(yōu)雅的對象結(jié)構(gòu)處理

    Java訪問者模式是一種行為型設(shè)計(jì)模式,它通過將數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)操作分離,實(shí)現(xiàn)對復(fù)雜對象結(jié)構(gòu)的處理。它將數(shù)據(jù)結(jié)構(gòu)中的每個元素都轉(zhuǎn)換為訪問者能夠識別的形式,從而使得數(shù)據(jù)操作可以在不影響數(shù)據(jù)結(jié)構(gòu)的前提下進(jìn)行擴(kuò)展和變化
    2023-04-04
  • 將Dubbo服務(wù)打包成Jar包的操作步驟

    將Dubbo服務(wù)打包成Jar包的操作步驟

    Dubbo 是一款流行的 Java RPC 框架,它提供了高性能、透明化的 RPC 遠(yuǎn)程服務(wù)調(diào)用方案,在開發(fā)基于 Dubbo 的服務(wù)時(shí),我們通常需要將服務(wù)代碼打包成可發(fā)布的 JAR 包,本文將詳細(xì)介紹如何將 Dubbo 服務(wù)打包成 JAR 包,并提供相應(yīng)的配置和步驟,需要的朋友可以參考下
    2024-12-12
  • 打印Java程序的線程棧信息方式

    打印Java程序的線程棧信息方式

    這篇文章主要介紹了打印Java程序的線程棧信息方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java中的Optional類用法詳細(xì)講解

    Java中的Optional類用法詳細(xì)講解

    這篇文章詳細(xì)介紹了Java中Optional類的使用,包括創(chuàng)建Optional對象,Optional對象的常用方法,如get、orElse、orElseGet、orElseThrow等,以及Optional類結(jié)合Lambda表達(dá)式和StreamAPI的使用,需要的朋友可以參考下
    2024-10-10
  • Mybatis返回單個實(shí)體或者返回List的實(shí)現(xiàn)

    Mybatis返回單個實(shí)體或者返回List的實(shí)現(xiàn)

    這篇文章主要介紹了Mybatis返回單個實(shí)體或者返回List的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java中實(shí)現(xiàn)多重排序的幾種方法小結(jié)

    Java中實(shí)現(xiàn)多重排序的幾種方法小結(jié)

    Java中的多重排序通常指的是同時(shí)對一個集合中的兩個或更多列或多維度的數(shù)據(jù)進(jìn)行排序,這通常通過自定義Comparator實(shí)現(xiàn),可以結(jié)合Arrays.sort()或Collections.sort()方法,當(dāng)需要進(jìn)行多重排序時(shí),即根據(jù)多個字段進(jìn)行排序,我們可以采用以下幾種方法
    2024-10-10
  • spring security獲取用戶信息的實(shí)現(xiàn)代碼

    spring security獲取用戶信息的實(shí)現(xiàn)代碼

    這篇文章主要介紹了spring security獲取用戶信息的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • mybatis調(diào)用mysql存儲過程并獲取返回值方式

    mybatis調(diào)用mysql存儲過程并獲取返回值方式

    這篇文章主要介紹了mybatis調(diào)用mysql存儲過程并獲取返回值方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • java開發(fā)flyway的方法

    java開發(fā)flyway的方法

    這篇文章主要介紹了java開發(fā)flyway的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Spring?c3p0配置的實(shí)現(xiàn)示例

    Spring?c3p0配置的實(shí)現(xiàn)示例

    在Spring框架中配置c3p0連接池可以提升數(shù)據(jù)庫操作性能,本文主要介紹了Spring?c3p0配置的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-09-09

最新評論

临湘市| 青海省| 来安县| 顺昌县| 江油市| 泸水县| 阳山县| 行唐县| 澎湖县| 重庆市| 辰溪县| 西藏| 清远市| 平湖市| 苗栗市| 延长县| 大渡口区| 壤塘县| 辽源市| 密山市| 宜昌市| 花垣县| 江达县| 准格尔旗| 自治县| 武定县| 西宁市| 彰化县| 南部县| 平乐县| 岳池县| 开远市| 西林县| 长宁区| 萝北县| 社会| 鲁甸县| 安溪县| 和龙市| 陇川县| 邳州市|