-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!!!) 数据块上工作。

任何事情都有可能发生。“任何事情”包括由于一些“巧合”,代码在大多数情况下都可以正常工作:

  • 手头的任务非常小。(只是一个补充)
  • 任务被创建并立即启动。
  • 两个“create+start”对之间有一个小的延迟: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应该是 a private volatile int(以便 Java 知道永远不会缓存它 - 它的值很可能在不同线程访问之间发生变化而下一个线程不知道)并制作Account#deposit(int amount)a public synchronized void(以便 Java 使方法体成为关键区域并防止同时访问任何它接触的对象,确保balance) 值的完整性。

此外,自己实例化 100 个线程new会带来很多开销——尽管我明白这只是一个玩具示例,但更有效的方法是使用Java 线程池

于 2012-12-16T17:45:31.313 回答