首页 > 解决方案 > Java 同步帐户示例未按预期工作

问题描述

我正在使用 Account 示例来练习 Java Synchronized。
这是我的代码。

账户类

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;
}

MyThread 类

 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....");
    }
}

线程测试类

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 完成了
我的工作 ....
完成了我的工作 ....
完成了我的工作 ....
帐号 9997 线程 0 执行...
帐号 9997 线程 2 执行 ....
帐号 9997 线程 1 执行...
account 9995 Thread-2performing....
account 9996 Thread-0performing....
account 9993 Thread-2performing....
account 9994 Thread-1performing....
account 9991 Thread-2performing....
account 9992 Thread-0performing ....
帐户 9989 线程 2 执行....
帐户 9990 线程 1 执行....
帐户 9987 线程 2 执行..
帐户 9988 线程 0 执行....
帐户 9985 线程 2 执行....
account 9986 Thread-1performing....
帐号
9713 Thread-1performing....
帐号 9708 Thread-1performing....
帐号 9709 Thread-0performing....
帐号 9706 Thread-0performing....
帐号9707 Thread-1performing....
账户 9704 Thread-1performing....
账户 9705 Thread-0performing....
账户 9702 Thread-0performing....
账户 9703 Thread-1performing....
账户 9701 Thread-0performing。 ...
帐户 9700 Thread-1 正在执行...

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

标签: javamultithreadingsynchronized

解决方案


System.out.println的未同步,例如:

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

如果要按顺序打印,请放入synchronizedfor循环。(Account#deduct2不再需要添加synchronized。):

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

推荐阅读