-1

Java でこのスレッド プログラムの何が問題なのかを突き止めようとしています。誰でも光を当てることができますか?コードは次のとおりです。

public class Z {
    private Account account = new Account();
    private Thread[] thread = new Thread[100];

    public static void main(String[] args) {
        Z test = new Z();
        System.out.println("What is balance ? " + test.account.getBalance());
    }

    public Z() {
        ThreadGroup g = new ThreadGroup("group");
        boolean done = false;

        // Create and launch 100 threads
        for (int i = 0; i < 100; i++) {
            thread[i] = new Thread(g, new AddAPennyThread(), "t" + i);
            thread[i].start();
            System.out.println("depositor: " + thread[i].getName());
        }
        // Check if all the threads are finished
        while (!done)
            if (g.activeCount() == 0)
                done = true;
    }

    // A thread for adding a penny to the account
    class AddAPennyThread extends Thread {
        public void run() {
            account.deposit(1);
        }
    }

    // An inner class for account
    class Account {
        private int balance = 0;

        public int getBalance() {
            return balance;
        }

        public void deposit(int amount) {
            int newBalance = balance + amount;
            balance = newBalance;
        }
    }
}

コンパイルして正常に実行されます。それは私が見逃したテストの質問であり、実際に何が間違っているのかを知りたがっていました. ありがとう!

4

3 に答える 3

4

100 個のスレッドすべてが正確に1 つ(1!!!) のデータで動作する同期専用のビットはありません。

何でも起こりえます。「何でも」には、いくつかの「偶然」により、ほとんどの場合、そのままのコードが機能することが含まれます。

  • 当面のタスクは非常に小さいです。(追加のみ)
  • タスクが作成され、すぐに開始されます。
  • 2 つの「作成 + 開始」ペアの間には、わずかな遅延があります: System.out.println.

これは次のようになります。これは、ほとんどのテスト実行で機能する可能性があります。しかし、これは不正確で非決定論的なプログラムです。

于 2012-12-16T17:37:20.783 に答える
0
[Tread1] int newBalance = balance + amount;
[Tread2] int newBalance = balance + amount;
[Tread1] balance = newBalance;
[Tread2] balance = newBalance;

public synchronized void deposit(int amount)
于 2012-12-16T17:41:23.333 に答える
0

balance(Javaがprivate volatile intそれを決してキャッシュしないことを認識します。その値は、次のスレッドが認識しない限り、異なるスレッド アクセス間で変更される可能性があります) でAccount#deposit(int amount)ある必要がありpublic synchronized void、Java がメソッド本体を重要な領域にし、いずれかの同時アクセスを防止するように、a にする必要があります。の値の完全性を保証するbalance)。

さらに、自分で 100 個のスレッドをインスタンス化するとnew、多くのオーバーヘッドが発生します。これはおもちゃの例に過ぎないことを理解していますが、これを行うより効率的な方法は、Java スレッド プールを使用することです。

于 2012-12-16T17:45:31.313 に答える