java - 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 一样运行.....
解决方案
您System.out.println
的未同步,例如:
- 起初金币为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....");
}
}
推荐阅读
- php - 我的网址按预期转到 ?error=none 但没有任何内容插入我的数据库?
- python-3.x - 创建新 blob 时使用 create_blob_from_bytes 方法。获取错误:指定的 blob 不存在。错误代码:未找到 Blob
- sql - Oracle SQL Developer 中是否有等效于禁用相关外键选项的 SQL 查询
- c# - 在 ComboBox 上显示所有进程
- google-cloud-platform - 如果目标表不是每日分区的,Bigquery 数据传输失败
- visual-studio-code - 错误:命令失败:C:\WINDOWS\System32\wslconfig.exe /list
- c# - VS2019 Typescript Intellisense 用于 cshtml 视图中的自定义 HtmlElement
- soap - 读取 OBIEE 实例配置文件
- c# - 如何结合 byte[] 和 ushort 枚举
- python - 使用 lil_matrix 读写