中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java線程安全狀態的示例分析

發布時間:2022-03-03 13:47:15 來源:億速云 閱讀:131 作者:小新 欄目:開發技術

這篇文章主要為大家展示了“Java線程安全狀態的示例分析”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“Java線程安全狀態的示例分析”這篇文章吧。

一、觀察線程的所有狀態

線程的狀態是一個枚舉類型 Thread.State

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

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

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

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

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

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

TERMINATED: 工作完成了.

二、線程狀態和狀態轉移的意義

Java線程安全狀態的示例分析

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

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

WAITING:wait方法導致

TIMED_WAITING:sleep方法導致

BLOCKED:等待鎖導致

TERMINATED:對象還在,但PCB已經沒了

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());
    }

Java線程安全狀態的示例分析

三、多線程帶來的風險

線程不安全的原因

①線程是搶占式執行的

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

②自增操作不是原子的

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

        把內存中的數據讀取到CPU中

        把CPU中的數據+1

        把計算的數據寫回內存中

Java線程安全狀態的示例分析

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

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

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

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

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

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

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

④內存可見性導致線程安全問題

⑤指令重排序

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

四,解決線程安全問題

鎖-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);
    }

Java線程安全狀態的示例分析

Java線程安全狀態的示例分析

Java線程安全狀態的示例分析

 已加鎖

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);
    }

Java線程安全狀態的示例分析

Java線程安全狀態的示例分析

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

synchronized的特性——刷新內存

synchronized 的工作過程:

        1. 獲得互斥鎖

        2. 從主內存拷貝變量的最新副本到工作的內存

        3. 執行代碼

        4. 將更改后的共享變量的值刷新到主內存

        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("輸入一個整數");
                    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();
    }

Java線程安全狀態的示例分析

一旦線程一獲取到鎖,并且沒有釋放的話,線程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("輸入一個整數");
                    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();
    }

Java線程安全狀態的示例分析

 不是同一把鎖,就不回出現競爭,就沒有互斥了。

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("輸入一個整數");
                    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();
    }

Java線程安全狀態的示例分析

這個代碼中,兩個線程都在針對locker1和locker2的類對象進行競爭,此處的locker1和locker2的類型都是Object,對應的對象都是相同的對象。 

以上是“Java線程安全狀態的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

靖西县| 育儿| 西昌市| 环江| 城市| 连州市| 乐业县| 桐庐县| 额尔古纳市| 汽车| 长垣县| 枣阳市| 和硕县| 乌审旗| 利津县| 永州市| 石河子市| 屏东县| 枣阳市| 商水县| 阳谷县| 保靖县| 得荣县| 巨野县| 曲阳县| 土默特右旗| 苍梧县| 如东县| 临漳县| 文昌市| 绍兴县| 依兰县| 吴旗县| 平顶山市| 邢台市| 广宁县| 浦东新区| 紫云| 四平市| 隆回县| 历史|