什麼是線程的安全問題?html
上一篇 Java基礎-多線程-①線程的建立和啓動 咱們說使用實現Runnable接口的方式來建立線程,能夠實現多個線程共享資源:安全
1 class Dog implements Runnable { 2 // 定義線程共享數據 3 private int t = 100; 4 5 @Override 6 public void run() { 7 // TODO:死循環,暫不處理 8 while (true) { 9 if (t > 0) { 10 11 System.out.println("當前線程:" + Thread.currentThread().getName() + "---" + t--); 12 } 13 } 14 } 15 } 16 17 public class ThreadDemo { 18 public static void main(String[] args) { 19 System.out.println("當前線程:" + Thread.currentThread().getName()); 20 Dog dog = new Dog(); 21 22 Thread thread = new Thread(dog); 23 Thread thread2 = new Thread(dog); 24 thread.start(); 25 thread2.start(); 26 27 } 28 }
開啓兩個線程,共享數據t=100,執行run方法中的代碼:當t大於0時,打印t--。分析一下可能會存在的問題:多線程
由於CPU時間片快速切換的不肯定性,該問題不必定會發生,爲了模擬一下該問題的發生,在打印語句執行前,讓線程睡眠0.1秒:ide
1 @Override 2 public void run() { 3 while (true) { 4 if (t > 0) { 5 try { 6 Thread.sleep(100); 7 System.out.println("當前線程:" + Thread.currentThread().getName() + "---" + t--); 8 } catch (InterruptedException e) { 9 //TODO:暫不處理異常 10 } 11 } 12 } 13 }
問題產生的緣由post
首先咱們想到是由於兩個線程共享了數據t。若是多個線程不涉及數據共享,各自執行本身的代碼,就不會出現這個問題。在線程不安全的單例模式中,就涉及到這個問題。spa
①多個線程共享了數據。線程
若是咱們不判斷t>0,直接打印t--,或者只判斷t>0,不執行t--,只要循環不結束,程序不終止,從邏輯上來講,程序也沒有問題設計
②在線程任務中設計對共享數據的操做(這裏的操做包括①判斷t>0;②執行t--),一個線程在操做共享數據的時候,其餘的線程也操做了共享數據。code
這時候就可能形成數據出錯。htm
總結來講,多個線程在執行同一段代碼的時候,每次的執行結果和單線程執行的結果都是同樣的,不存在執行結果的二義性,就能夠稱做是線程安全的。線程安全問題可能是由全局變量和靜態變量引發的,當多個線程對共享數據只執行讀操做,不執行寫操做時,通常是線程安全的;當多個線程都執行寫操做時,須要考慮線程同步來解決線程安全問題。