目前共有5篇帖子。
【程序】Java線程同步
1樓 巨大八爪鱼 2016-11-7 19:21

public class Test {
    
    public static void main(String[] args) {
        Saler s = new Saler();
        for (int i = 1; i <= 4; i++) {
            Thread t = new Thread(s);
            t.setName("Seller " + i);
            t.start();
        }
    }

}

public class Saler implements Runnable {
    private int tickets = 100;
   
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        while (tickets > 0) {
            synchronized (this) {
                if (tickets > 0) { // 不能省略!否則會出現0, -1, -2被賣出的情況
                    System.out.println(name + ": " + tickets);
                    tickets--;
                    try {
                        Thread.sleep((long)(Math.random() * 1500));
                    } catch (InterruptedException e) {
                       
                    }
                }
            }
        }
    }
}

2樓 巨大八爪鱼 2016-11-7 19:21
【輸出】
Seller 1: 100
Seller 3: 99
Seller 3: 98
Seller 3: 97
Seller 3: 96
Seller 4: 95
Seller 4: 94
Seller 4: 93
Seller 4: 92
Seller 4: 91
Seller 4: 90
Seller 4: 89
Seller 4: 88
Seller 4: 87
Seller 4: 86
Seller 4: 85
Seller 2: 84
Seller 4: 83
Seller 3: 82
Seller 3: 81
Seller 3: 80
Seller 3: 79
Seller 3: 78
Seller 3: 77
Seller 3: 76
Seller 3: 75
Seller 3: 74
Seller 3: 73
Seller 3: 72
Seller 3: 71
Seller 1: 70
Seller 1: 69
Seller 3: 68
Seller 3: 67
Seller 3: 66
Seller 3: 65
Seller 4: 64
Seller 2: 63
Seller 2: 62
Seller 2: 61
Seller 2: 60
Seller 2: 59
Seller 2: 58
Seller 4: 57
Seller 3: 56
Seller 1: 55
Seller 1: 54
Seller 1: 53
Seller 3: 52
Seller 3: 51
Seller 3: 50
Seller 4: 49
Seller 4: 48
Seller 4: 47
Seller 4: 46
Seller 4: 45
Seller 4: 44
Seller 4: 43
Seller 4: 42
Seller 2: 41
Seller 2: 40
Seller 2: 39
Seller 4: 38
Seller 3: 37
Seller 3: 36
Seller 3: 35
Seller 3: 34
Seller 3: 33
Seller 3: 32
Seller 3: 31
Seller 3: 30
Seller 3: 29
Seller 3: 28
Seller 1: 27
Seller 1: 26
Seller 1: 25
Seller 3: 24
Seller 3: 23
Seller 3: 22
Seller 3: 21
Seller 4: 20
Seller 4: 19
Seller 2: 18
Seller 4: 17
Seller 4: 16
Seller 4: 15
Seller 4: 14
Seller 3: 13
Seller 3: 12
Seller 3: 11
Seller 3: 10
Seller 3: 9
Seller 3: 8
Seller 3: 7
Seller 1: 6
Seller 1: 5
Seller 3: 4
Seller 4: 3
Seller 2: 2
Seller 2: 1
3樓 巨大八爪鱼 2016-11-7 19:24
synchronized (this) {
此代碼將整個Saler對象鎖住,當第一個線程和第二個線程同時訪問Saler.tickets變量時,第二個線程將會卡在synchronized那裡,等待第一個線程的synchronized語句塊執行完畢。
4樓 巨大八爪鱼 2016-11-7 19:26
可以將synchronized語句塊單獨寫成一個函數,這樣該函數就不能同時被兩個線程執行:
public class Saler implements Runnable {
    private int tickets = 100;
    
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        while (tickets > 0) {
            sell(name);
        }
    }

    private synchronized void sell(String name) {
        if (tickets > 0) { // 不能省略!否則會出現0, -1, -2被賣出的情況
            System.out.println(name + ": " + tickets);
            tickets--;
            try {
                Thread.sleep((long)(Math.random() * 1500));
            } catch (InterruptedException e) {
                
            }
        }
    }
}


5樓 巨大八爪鱼 2016-11-7 19:31
雖然while語句里的條件確保了tickets不會小於1,但是由於線程在執行過程中可能會卡在synchronized語句上,等到繼續執行時tickets可能已被其他線程減為小於1的數,從而出現輸出0, -1, -2的情況,這需要通過一個if語句來避免。

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
 
 
©2010-2024 Arslanbar [手機版] [桌面版]
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。