首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java 多執行緒賣票問題:static 變數競態條件與 synchronized 修正

     編輯:程式設計綜合問答

錯誤代碼

public static int count = 5; // 共享變數
public void run() {
    for (int i=0; i<=4; i++) {
        Thread.sleep(1000);
        if (count > 0) {
            System.out.println(Thread.currentThread().getName() + ",count= " + this.count--);
        }
    }
}

問題分析

  • count > 0 檢查與 count-- **非原子操作**,三個執行緒可能同時通過判斷,導致**超賣**(輸出出現重複數字、負數)。
  • int 非 volatile,甚至可能發生**可見性問題**(執行緒讀到舊值)。

修正方案

  1. synchronized 鎖住共享變數(最簡單):
private static final Object lock = new Object();
// 或直接 synchronized(this) 但 this 可能不同實例,靜態變數鎖類對象更好
synchronized (Ticket.class) {
    if (count > 0) {
        System.out.println(Thread.currentThread().getName() + ",count= " + count--);
    }
}
  1. AtomicInteger 無鎖 CAS(高併發推薦):
private static final AtomicInteger count = new AtomicInteger(5);
public void run() {
    for (int i=0; i<5; i++) {
        Thread.sleep(1000);
        int current = count.decrementAndGet(); // 原子遞減並取新值
        if (current >= 0) {
            System.out.println(Thread.currentThread().getName() + ",count= " + current);
        }
    }
}

輸出對比

修正後:**無重複、無負數、總數精確為 5**,三個執行緒輪流賣完 5 張票。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved