Java 同步帐户示例未按预期运行

Java Synchronized account example isn't working as expected

我正在使用帐户示例来练习 Java 同步。
这是我的代码。

帐号class

class Account {

public int dollars;

public Account(int d) {
    dollars = d;
}

// might fail due to concurrently accessing this method
public synchronized void deduct2(int amount) {
      dollars -= amount;
}

@Override
public String toString() {
    return "" + dollars;
}

我的线程class

 class MyThread extends Thread {
static Account account = new Account(10000);

private int id;

public MyThread(int i) {
    id = i;
}

@Override
public void run() {
    System.out.println("performing my job ....");
    for (int i = 0; i < 100; i++) {
        account.deduct2(1);
        System.out.println("account " + account + "  " + getName() +"performing....");
    }
}

线程测试class

public class ThreadTest {

public static void main(String args[]) {
    new ThreadTest().exec();
    System.out.println("main finished");
}

private void exec() {
    test1();
}

private void test1() {
    Thread thread1 = new MyThread(1);
    Thread thread2 = new MyThread(2);
    Thread thread3 = new MyThread(3);
    thread1.start();
    thread2.start();
    thread3.start();

}}

结果

main finished
performing my job ....
performing my job ....
performing my job ....
account 9997 Thread-0performing....
account 9997 Thread-2performing....
account 9997 Thread-1performing....
account 9995 Thread-2performing....
account 9996 Thread-0performing....
account 9993 Thread-2performing....
account 9994 Thread-1performing....
account 9991 Thread-2performing....
account 9992 Thread-0performing....
account 9989 Thread-2performing....
account 9990 Thread-1performing....
account 9987 Thread-2performing....
account 9988 Thread-0performing....
account 9985 Thread-2performing....
account 9986 Thread-1performing....
....
account 9713 Thread-1performing....
account 9708 Thread-1performing....
account 9709 Thread-0performing....
account 9706 Thread-0performing....
account 9707 Thread-1performing....
account 9704 Thread-1performing....
account 9705 Thread-0performing....
account 9702 Thread-0performing....
account 9703 Thread-1performing....
account 9701 Thread-0performing....
account 9700 Thread-1performing....

我运行三个不同的新线程,每个新线程扣1一百次。所以账户美元的结果是正确的(9700)。
但我很困惑,为什么扣除账户美元的过程没有按我的预期进行。我假设它会 运行 像 9999 9998 9997.....

您的System.out.println不同步,例如:

  1. 一开始dollers是10000 , thread1thread2 执行 account.deduct2(1);现在dollers是9998.
  2. thread3执行account.deduct2(1);现在dollers是9997.
  3. thread1thread2开始打印account#dollars,你会看到两个9997.

如果要顺序打印,将synchronized放在for循环中。(Account#deduct2不需要再添加synchronized。):

       for (int i = 0; i < 100; i++) {
            synchronized (account) {
                account.deduct2(1);
                System.out.println("account " + account + "  " + getName() + "performing....");
            }
        }