是的,代碼存在錯誤,原因如下:
競爭條件(Race Condition):多個線程同時修改bank對象的value屬性,沒有適當的同步措施,導致寫操作發生覆蓋,進而造成某些加法操作沒有被正確記錄。
線程完成檢測方法不可靠:使用ThreadGroup.activeCount()檢查活躍線程數量以判斷所有線程是否完成是不可靠的。因為activeCount()只是一個估計,可能不准確,特別是在高負載或者複雜的線程管理情境下。
要解決這些問題,我們需要:
同步訪問共用資源:使用synchronized關鍵字或Lock介面來確保在任何時刻只有一個線程可以修改value。
安全地等待線程完成:使用join()方法在主線程中等待所有的子線程完成,或使用CountDownLatch、CyclicBarrier、Semaphore或Future來控制線程的執行。
下麵是修改後的代碼段,展示了如何使用synchronized關鍵字同步方法,並使用join()來等待線程完成:
java
Copy code
class Bank {
private int value = 0;
public synchronized int getValue() { return value; }
public synchronized void setValue(int value) { this.value = value; }
}
class AddThread extends Thread {
private Bank bank;
public AddThread(Bank bank) {
this.bank = bank;
}
public void run() {
int newValue = bank.getValue() + 1;
try { Thread.sleep(5); }
catch (InterruptedException ex) { System.out.println(ex); }
bank.setValue(newValue);
}
}
public class ClassA {
private Bank B = new Bank();
private Thread[] thread = new Thread[10];
public ClassA() throws InterruptedException {
for (int i = 0; i < 10; i++) {
thread[i] = new AddThread(B);
thread[i].start();
}
for (int i = 0; i < 10; i++) {
thread[i].join(); // 等待每個線程完成
}
}
public static void main(String[] args) throws InterruptedException {
ClassA test = new ClassA();
System.out.println("What is the result? " + test.B.getValue());
}
}
在這個修正的版本中,Bank的getValue和setValue方法都被聲明為synchronized,這樣在同一時刻只有一個線程能夠訪問它們。此外,在ClassA的構造函數中,我們對每個AddThread調用了join()方法,確保所有的線程都執行完畢後,主線程才會繼續執行並列印最終的結果。這樣可以保證結果總是正確的,且為10。