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
不同步,例如:
- 一开始dollers是10000
,
thread1
和 thread2
执行 account.deduct2(1)
;现在dollers是9998.
thread3
执行account.deduct2(1)
;现在dollers是9997.
thread1
和thread2
开始打印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....");
}
}
我正在使用帐户示例来练习 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
不同步,例如:
- 一开始dollers是10000
,
thread1
和thread2
执行account.deduct2(1)
;现在dollers是9998. thread3
执行account.deduct2(1)
;现在dollers是9997.thread1
和thread2
开始打印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....");
}
}