阿摩線上測驗 登入

申論題資訊

試卷:98年 - 098年專門職業及技術人員高等建築師、技師、消防設備師、普通不動產經紀人、記帳士、第二次消防設備士暨語言治療師資訊技師#32441
科目:程式設計
年份:98年
排序:0

題組內容

四、假設有下列 Java Thread 程式碼: 

申論題內容

⑵結果是否有錯誤?若有錯誤,是何原因?該如何解決?(10 分)

詳解 (共 1 筆)

詳解 提供者:hchungw
是的,代碼存在錯誤,原因如下:
競爭條件(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。