国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > ASM > 正文

從匯編去分析線程安全

2019-11-14 22:39:05
字體:
來源:轉載
供稿:網友
從匯編去分析線程安全

首先要知道什么是線程安全?

  當多個線程訪問某個類時,不管運行環境采用何種調度方式或者這些線程將如何交替執行,并且在主調代碼中不需要任何額外的同步或協同,這個類都能表現出正確的行為,那么就稱這個類是線程安全的。

典型線程不安全的列子:

 1 import java.util.*; 4  5 class Worker implements Runnable { 6     PRivate UnsafeCount unsafeCount; 7  8     public Worker(UnsafeCount unsafeCount) { 9         this.unsafeCount = unsafeCount;10     }11 12     @Override13     public void run() {14         // TODO Auto-generated method stub15         for (int i = 0; i < 1000; i++)16             unsafeCount.increase();17     }18 19 }20 21 public class UnsafeCount {22     private int count = 0;23 24     public void increase() {25         count++;26     }27 28     public int getCount() {29         return count;30     }31 32     public static void main(String[] args) throws InterruptedException {33         UnsafeCount uc = new UnsafeCount();34         35         //這里用了list簡陋的方式控制線程的結束,更好的實現是用閉鎖CountDownLatch或者柵欄CyclicBarrier36         List<Thread> list = new ArrayList<Thread>();//37         38         for (int i = 0; i < 10; i++) {39             Thread worker = new Thread(new Worker(uc));40             worker.start();41             list.add(worker);42         }43 44         //阻塞直到線程結束45         for (Thread t : list) {46             t.join();47         }48 49         System.out.println("total is: " + uc.getCount());50 51     }52 }

運行結果(每次結果都不一樣):total is: 7628

我們來仔細分析一下這個結果,開啟10個線程運行,每個線程都對count進行了1000次自增操作,期望的結果應該是1000*10=10000。很明顯運行結果與期望結果不一致。結論是這個類是線程不安全的。為什么會出現這種情況了?

原因是count++這個操作不是原子性,其實這個自增操作是個復合操作:讀-改-寫。 如果我們了解匯編語言的話,對應自增操作的匯編程序可能是:

movl count, %eax  #將count的值讀入eax的寄存器中,inc %eax  #寄存器eax里的值加1,即改寫count值movl %eax, %ebx  #這里ebx寄存器存存放著count的內存地址,這里是值將改寫的count值寫入到內存中

那么這樣就存在一個問題,假如就存在2個線程A和B操作變量count,初始化時刻count為0. 在線程A未寫入改寫值之前,比如在A線程執行步驟2的時刻, 線程B開始執行,如下所示:

線程A讀入count值為0(步驟1)  -》  改寫count值為1(步驟2)  -》 將改寫后的count值寫入內存中(步驟3) 

                    線程A讀入count值為0 (步驟1)  -》  改寫count值為1(步驟2)  -》 將改寫后的count值寫入內存中(步驟3)

因為線程A還沒有更新改寫count的值到內存,這時線程B讀入count的值仍舊是0,導致最后2個線程結束后count的值為1。由此可見做了2次自增的操作,期望結果是2,但實際結果可能是1.這也是線程不安全的情況下,自增的操作的實際結果往往比期望結果小的原因。

下篇準備將講什么情況是線程不安全的。

  


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 自贡市| 宁德市| 广河县| 渝北区| 翁牛特旗| 齐齐哈尔市| 彰化县| 阿鲁科尔沁旗| 万载县| 仙桃市| 仙游县| 丰台区| 临清市| 黄陵县| 昌乐县| 盐边县| 乡城县| 花莲县| 柳林县| 克什克腾旗| 永安市| 象山县| 平潭县| 文安县| 绥阳县| 塔河县| 盱眙县| SHOW| 遵义市| 新河县| 长宁县| 讷河市| 镇远县| 平泉县| 大石桥市| 鄯善县| 昌黎县| 微博| 长寿区| 平湖市| 察雅县|