public class Bank { private int sum=0; public void add(int n) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } sum+= n; System.out.println(sum); }}public class Consumer implements Runnable { Bank bank = new Bank(); @Override public void run() { for (int i = 0; i < 10; i++) { bank.add(100); } }}public class Tes2 { public static void main(String[] args) { Consumer consumer = new Consumer(); Thread thread1 = new Thread(consumer); Thread thread2 = new Thread(consumer); thread1.start(); thread2.start(); }}這是一個多線程程序,模擬多個儲戶到銀行存錢,用來演示多線程的安全問題。由于代碼不同步,它的第一、第二個結果可能是200/200,200/300,等等。但是我不明白為什么你得到100/100,誰能解釋一下?
2 回答

撒科打諢
TA貢獻1934條經驗 獲得超2個贊
這是一個競爭條件。
兩個線程都可以訪問 sum。
總和+=n;不是原子的
線程 1 讀取 sum 0
線程 2 換入,因為代碼未同步,讀取 sum 為 0
線程 1 將 100 加到 0 并將其寫入總和
線程 2 將 0 加 100 并將其寫入總和并覆蓋線程 1 的值

神不在的星期二
TA貢獻1963條經驗 獲得超6個贊
如果您僅根據代碼中的行來考慮該程序的并發性,那么 100/100 的輸出結果就沒有意義。但您還必須考慮執行這些行時實際發生的指令是什么。每行代碼可以包含很多很多匯編指令。在這種情況下,要添加n
到sum
,真正發生的是從內存中讀取 的值sum
,可能加載到寄存器中,遞增,然后重新寫入內存中。
100/100 輸出可能發生在以下場景中。假設線程 1 和線程 2 都調用bank.add(100)
,并且銀行異步處理請求。也就是說,銀行有一個線程處理每個請求。
然后,該組的線程 1 加載 的值sum
,該值為零。線程 2 還加載了緊隨其后的值sum
,該值仍然為零。然后,線程 1 獲取它加載的值,添加n=100
,并將其寫入內存。線程2做同樣的事;它采用之前加載的 sum 值 0,加上 100,然后將其寫回內存。然后,他們各自打印出 100 的值。
添加回答
舉報
0/150
提交
取消