|
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) { } } } } } }
|
|
【輸出】 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
|
|
synchronized (this) { 此代碼將整個Saler對象鎖住,當第一個執行緒和第二個執行緒同時訪問Saler.tickets變數時,第二個執行緒將會卡在synchronized那裡,等待第一個執行緒的synchronized語句塊執行完畢。
|
|
可以將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) { } } } }
|
|
雖然while語句里的條件確保了tickets不會小於1,但是由於執行緒在執行過程中可能會卡在synchronized語句上,等到繼續執行時tickets可能已被其他執行緒減為小於1的數,從而出現輸出0, -1, -2的情況,這需要通過一個if語句來避免。
|