- 之所以造成這個誤解,大概跟線程安全的幾種解決手段有關(guān).
目前公認的幾種線程安全的解決手段:
- 同步技術(shù)
- 多用方法內(nèi)局部變量
- ThreadLocal技術(shù)(一線程,一實例變量copy)
除同步技術(shù)外,另兩種解決手段都是"anti_sharing",實際是犧牲了多并發(fā)線程下的資源的共享特性.
多線程的共享資源的實際值會和理論值
不一致,這樣就叫作"線程不安全"
而
多線程對共享資源的改變,也是理論值之一.即理論上是接受共享資源被多個線程改變的.我們舉最常見的"多線程售票"的例子,很多人在學習多線程都是從這個例子開始的.
下面這段程序是存在線程安全問題的,但"共享售票"并不意味著線程不安全
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() ; // 再一個線程開始賣票 }
|
執(zhí)行: 賣票:ticket = 5 賣票:ticket = 4 賣票:ticket = 3 賣票:ticket = 2 賣票:ticket = 1
|
因為程序執(zhí)行太快了,來不及顯性產(chǎn)生線程安全問題,我們在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--);
|
運行結(jié)果如下: 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時兩個線程都通過測試,都進行了--,就出現(xiàn)了-1
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點擊舉報。