- 原文:點擊打開鏈接
- 之所以造成這個誤解,大概跟線程安全的幾種解決手段有關.
- 同步技術
- 多用方法內局部變量
- ThreadLocal技術(一線程,一實例變量copy)
- 線程安全的定義:
而多線程對共享資源的改變,也是理論值之一.即理論上是接受共享資源被多個線程改變的.
- 舉例如下:
下面這段程序是存在線程安全問題的,但"共享售票"並不意味着線程不安全
public class MyThread implements Runnable { private int ticket = 5; // 一共才5張票,會被多線程共同賣出 public void run() { for (int i = 0; i < 50; i++) { if (this.ticket > 0) { System.out.println("賣票:ticket = " + this.ticket--); } } } } public static void main(String[] args) { MyThread mt = new MyThread(); // 單實例 new Thread(mt).start() ; // 一個線程開始賣票 new Thread(mt).start() ; // 另一個線程開始賣票 new Thread(mt).start() ; // 再一個線程開始賣票 } |
執行: 賣票:ticket = 5 賣票:ticket = 4 賣票:ticket = 3 賣票:ticket = 2 賣票:ticket = 1 |
因爲程序執行太快了,來不及顯性產生線程安全問題,我們在run()中加一個Thread.sleep(300)方法
public void run() { for (int i = 0; i < 50; i++) { if (this.ticket > 0) { try { Thread.sleep(300);// 延遲 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("賣票:ticket = " + this.ticket--); |
運行結果如下: D:\java\source\thread\sync>java syndemo.SynDemo01 賣票:ticket = 5 賣票:ticket = 4 賣票:ticket = 3 賣票:ticket = 2 賣票:ticket = 1 賣票:ticket = 0 賣票:ticket = -1 這就是理論值(this.ticket > 0)與實際值(-1)不符, 反映了線程安全的概念定義 |
當剩最後一張票時
上一個進程通過了(this.ticket > 0)的判斷,卻sleep了,沒來得及把this.ticket--
而另一個進程趁機也通過了(this.ticket > 0)的判斷
這樣就形成了ticket=1時兩個線程都通過測試,都進行了--,就出現了-1