1. 程式人生 > >Java執行緒併發與安全性問題詳解

Java執行緒併發與安全性問題詳解

併發與執行緒安全問題詳解

  • 什麼是併發
  • 執行緒併發安全問題

什麼是併發

想要解決執行緒併發安全問題,那首先要弄清楚什麼是併發?
- 執行緒的併發原理:
- 我們先舉一個例子,在你做數學題的時候能不能同時背課文,有些同學說可以一心二用啥的,咱就說正常人好吧!你會發現一個正常人是沒有辦法在做數學題的同時背課文的,如果你非要同時做這個兩件事情,那麼結果是什麼樣呢?我們來模擬一下:1)寫個題目,背一句課文2)先做完數學題,再背語文課文。當然了,具體怎麼做要看你的心情,並沒有固定的方式。但是你會發現不可能出現一種情況就是在同一時刻寫數學題並且背課文,問什麼呢,因為你就一個大腦!
- 就像你的大腦一樣,它不能同時做兩件不相關的事情。同樣的,電腦的CPU也不能同時處理兩個及以上的執行緒,如果有多個任務則多個任務是輪流佔用CPU的,所有實際上多個執行緒並不是同時執行的,而每個執行緒都是走走停停的(就像你寫一下題目,再看一下課文一樣。當然我們說併發都是針對一個一個CPU而言的,現在的雙核或四核CPU是可以同時處理多個任務的)。


- 下面我們用程式碼來驗證執行緒的併發性

class Two extends Thread{
    public void run(){
        for(int i=1;i<=50;i++){
            System.out.println(i);
        }
    }
}
public class TestThread{
        public static void main(String[] args) {
        //建立了t1執行緒
        Thread t1=new Two();
        //建立t2執行緒
        Thread t2=new
Two(); t1.start(); t2.start(); } }

多次執行上述程式碼你會得到執行緒併發性的結果。

執行緒併發安全問題

我們已經知道了併發,那執行緒安全問題是指什麼?同樣的我們先來舉個例子。
小明和小紅從鍋裡撈餃子,餃子數量為5,每撈一個減一,當最後只剩下一個餃子時,小明先看到了,然後下手去撈,這時小紅眼疾手快給撈了起來,此時鍋裡還剩0個餃子,但是小明也已經下手,此時就應該還剩-1個餃子,顯然是不符合邏輯的。
所以執行緒安全問題就是由多個執行緒併發訪問同一個資料(臨界資源)時可能會出現先後更改此資料而得到的資料不一致。
常見的臨界資源:
- 多執行緒共享例項變數
- 多執行緒共享靜態公共變數
下面我們用程式碼來做個測試

public class DemoSyn {
    static Integer num=10;
    public static void main(String[] args) {
        final DemoSyn syn=new DemoSyn();
        Thread t1=new Thread(){
            public void run(){
                syn.printNum(0);
            }
        };
        Thread t2=new Thread(){
            public void run(){
                syn.printNum(1);
            }
        };
        t1.start();
        t2.start();
    }
    public  void printNum(int i){
            if(i==0){
                num=100;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }else{
                num=200;
            }
            System.out.println(num);
    }
}

上述程式碼我們預期應該是會出現100,200或者200,100,但是執行你會發現出現結果大部分是100,100和200,200。這就是因為執行緒的不安全導致的。
下面我們分析以下原因:當執行緒t1先執行時,更改num值為100,然後此執行緒阻塞,執行緒t2佔用CPU,更改num值為200然後輸出,1000毫秒之後t1執行緒繼續執行,但是此時num的值已經被t2執行緒更改。所以結果是200,200(其他答案也可按照此過程推出)。