Java多線程-線程安全

1. 數據不共享的狀況html

在探討數據共享的話題前,先來看看數據不共享的狀況,每個線程裏面的數據都是獨立的,就像下面的例子,3個線程,每個線程本身對本身的數據進行扣減,直到0爲止安全

public class TestThread { public static void main(String[] args) { MyThread myThread_A = new MyThread("A"); MyThread myThread_B = new MyThread("B"); MyThread myThread_C = new MyThread("C"); myThread_A.start(); myThread_B.start(); myThread_C.start(); } } class MyThread extends Thread { private int count = 5; private String name; public MyThread(String name) { this.name = name; } @Override public void run() { // super.run();

        while (count != 0) { System.out.println(name + " = " + count); count--; } } }

 

運行結果:多線程

 

2. 數據共享的狀況ide

這裏有一段測試代碼,看看共享數據的結構,按照理想的狀況下,MyRunnable只實例了一次,因此裏面的count=5將會被扣減5次,打印的結果應該是,5,4,3,2,1,由於這裏有5個線程,每次調用run的時候,都會減去1,可是結果,確實有點出乎意外....並且每一次執行的結果都不同函數

public class TestThread { public static void main(String[] args) { //新建一個帶有Runnable接口的類
        MyRunnable myRunnable = new MyRunnable(); //新建5個線程,但使用了同一個Runnable實例對象,意味着裏面的數據是共享的 //這裏的Thread(Runnable,String)是一個構造函數,第一次參數爲Runnable接口,第二個爲線程名稱
        Thread thread_A = new Thread(myRunnable,"A"); Thread thread_B = new Thread(myRunnable,"B"); Thread thread_C = new Thread(myRunnable,"C"); Thread thread_D = new Thread(myRunnable,"D"); Thread thread_E = new Thread(myRunnable,"E"); thread_A.start(); thread_B.start(); thread_C.start(); thread_D.start(); thread_E.start(); } } class MyRunnable implements Runnable { private int count = 5; public MyRunnable() { } @Override public void run() { // super.run();
        System.out.println("當前線程名稱" + Thread.currentThread().getName() + " = " + count); count--; } }

 

運行結果1:測試

 

運行結果2:this

 

 

運行結果3:spa

 

 

3.線程不安全線程

通過上面的例子隱身出了一個問題,就是線程安全問題,在實際場景當中,這是一個很是危險的問題,例如在雙11,秒殺,活動中,不少買家同時在0點的時候按購買,但貨品只有1個,很明顯這裏就是多線程處理同一個數據(貨品庫存量),那若是在線程不安全的狀況下,會出現更上面例子同樣的狀況,兩我的同一時間都在對同一個數字進行處理,結果有多是,多名買家同時得到這個商品。3d

爲何這樣呢,主要緣由是count--這個代碼,通常狀況,這行代碼作了3個動做

  1. 獲取count當前的值
  2. 對count的值進行-1的動做
  3. 對count從新賦值

那問題很明顯就出在第一步,假如A線程運行到這一行代碼獲取到count的值爲5,接下來,B線程搶到CPU的使用前,他也執行到了這行代碼,獲取count的值也是5,由於A線程尚未進行-1的操做

 

4.線程安全

那怎麼辦呢,關鍵字synchronized,在run方法前加上這句的代碼就能夠達到排隊執行方法的做用了,意思就是說,在執行run代碼的時候,線程先查看當前代碼塊有沒有鑰匙,若是有鑰匙,便可進入這扇門(代碼塊),而後執行裏面的內容,執行完以後就會把鑰匙交出來,由下一個搶到鑰匙的人進入,並執行裏面的內容。在這個搶鑰匙的過程當中是人人平等,誰先搶到鑰匙,誰先進入。咱們叫這塊區域「互斥區」。

class MyRunnable implements Runnable { private int count = 5; public MyRunnable() { } @Override synchronized public void run() { // super.run();
        System.out.println("當前線程名稱" + Thread.currentThread().getName() + " = " + count); count--; } }

 

運行結果1:

 

運行結果2:

 

原文出處:https://www.cnblogs.com/oscar1987121/p/10220639.html

相關文章
相關標籤/搜索