欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2022年03月02日 14:27:18   作者:/少司命  
線程安全是多線程編程時的計算機程序代碼中的一個概念。在擁有共享數(shù)據(jù)的多條線程并行執(zhí)行的程序中,線程安全的代碼會通過同步機制保證各個線程都可以正常且正確的執(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: 這幾個都表示排隊等著其他事情

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

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

TERMINATED: 工作完成了.

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

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

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

WAITING:wait方法導致

TIMED_WAITING:sleep方法導致

BLOCKED:等待鎖導致

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("線程運行中:" + t.getState());
        }
        System.out.println("線程結束后:" + t.getState());
    }

三、多線程帶來的風險

線程不安全的原因

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

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

②自增操作不是原子的

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

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

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

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

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

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

必須保證線程1save結束了,線程2再load,此時計算結果才正確

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

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

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

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

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

⑤指令重排序

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

四,解決線程安全問題

鎖-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這個對象來加鎖,進入increase方法內(nèi)部,就把加鎖狀態(tài)設為ture,increase方法退出之后,就把加鎖狀態(tài)設為false,如果某個線程已經(jīng)把加鎖狀態(tài)設為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的類對象進行競爭,此處的locker1和locker2的類型都是Object,對應的對象都是相同的對象。?

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

相關文章

  • Java連接redis報錯timed?out問題的解決辦法

    Java連接redis報錯timed?out問題的解決辦法

    最近項目開發(fā)中用到了Redis,下面這篇文章主要給大家介紹了關于Java連接redis報錯timed?out問題的解決辦法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-02-02
  • Java中常用的四種引用類型詳解

    Java中常用的四種引用類型詳解

    Java中常用的四種引用類型,分別為,強引用、軟引用、弱引用以及虛引用,這篇文章主要為大家介紹了這四種引用的用法,需要的可以參考一下
    2023-06-06
  • @valid 無法觸發(fā)BindingResult的解決

    @valid 無法觸發(fā)BindingResult的解決

    這篇文章主要介紹了@valid 無法觸發(fā)BindingResult的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Hibernate連接三種數(shù)據(jù)庫的配置文件

    Hibernate連接三種數(shù)據(jù)庫的配置文件

    今天小編就為大家分享一篇關于Hibernate連接三種數(shù)據(jù)庫的配置文件,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • spring循環(huán)依賴策略解析

    spring循環(huán)依賴策略解析

    這篇文章主要為大家詳細介紹了spring循環(huán)依賴策略,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • java中dart類詳細講解

    java中dart類詳細講解

    這篇文章主要介紹了dart類詳細講解,實例講解的很清晰,有對于這方面不太清楚的同學可以跟著學習下
    2021-02-02
  • SpringBoot接收前端參數(shù)的幾種方式分享

    SpringBoot接收前端參數(shù)的幾種方式分享

    這篇文章給大家分享幾種SpringBoot接收前端參數(shù)的方式,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2023-09-09
  • 基于java中正則操作的方法總結

    基于java中正則操作的方法總結

    本篇文章介紹了,在java中正則操作的方法總結。需要的朋友參考下
    2013-05-05
  • SpringBoot詳解如果通過@Value注解給靜態(tài)變量注入值

    SpringBoot詳解如果通過@Value注解給靜態(tài)變量注入值

    這篇文章主要介紹了springboot如何通過@Value給靜態(tài)變量注入值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 高分面試從Hotspot源碼層面剖析java多態(tài)實現(xiàn)原理

    高分面試從Hotspot源碼層面剖析java多態(tài)實現(xiàn)原理

    這篇文章主要為大家介紹了在面試中從Hotspot源碼層面來剖析java多態(tài)的實現(xiàn)原理,這樣回答薪資隨你開,有需要的朋友可以借鑒參考下,希望大家多多加薪
    2022-01-01

最新評論