原野码农 2023-02-13 18:03 采纳率: 100%
浏览 28
已结题

多线程synchronized

使用synchronized同步线程,同一个账号取款的例子。在run方法中输出的金额有时候是不对的,如图,正常来说是900,800。但是多次运行发现有800,800的情况。
代码如下:

//同一账户同步取款
public class testSynchronized {
    public static void main(String[] args) {
        Account act = new Account("act-1", 1000);
        Thread t1 = new AccountThread(act);
        Thread t2 = new AccountThread(act);

        t1.setName("t1");
        t1.setName("t2");
        t1.start();
        t2.start();
    }
}

//取款线程
class AccountThread extends Thread {
    private Account act;
    //通过构造方法传递过来账户对象
    public AccountThread(Account account) {
        this.act = account;
    }

    @Override
    public void run() {
        Integer amount = 100;  //取款金额
        if (act.getBalance() > 0) {
            act.withdraw(amount);
            System.out.println("---" + act.getBalance());
        }
    }
}


//账户类
class Account {
    private String actno;   //账号
    private Integer balance;  //余额

    public Account(String actno, Integer balance) {
        this.actno = actno;
        this.balance = balance;
    }

    //取款方法
    public void withdraw(Integer amount) {
        synchronized (this) {//取款
            if (this.getBalance() == 0) {
                return;
            }
            Integer after = this.getBalance() - amount;
            this.setBalance(after);
            try {
                Thread.sleep(1000);
                System.out.println(this.getActno() + " 取款: " + amount + " ,余额: " + this.getBalance() + "  ---> " + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public String getActno() {
        return actno;
    }

    public void setActno(String actno) {
        this.actno = actno;
    }

    public Integer getBalance() {
        return balance;
    }

    public void setBalance(Integer balance) {
        this.balance = balance;
    }
}


如下:

img

  • 写回答

3条回答 默认 最新

  • 社区专家-Monster-XH 2023-02-13 18:05
    关注

    这是因为在代码中对同一个账户并发取款,导致了竞争条件。在AccountThread中,如果在两个线程取款的时候同时进入了withdraw方法,此时会发生余额被多次扣除,导致不正确的情况。

    针对这个问题,你需要在Account的withdraw方法上加上synchronized关键字,来保证同一时刻只有一个线程在取款操作,从而避免竞争条件。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 2月22日
  • 已采纳回答 2月14日
  • 创建了问题 2月13日

悬赏问题

  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥15 键盘指令混乱情况下的启动盘系统重装