Java [synchronized] 问题请教

本贴最后更新于 1769 天前,其中的信息可能已经东海扬尘

先上 代码 后提问

Main.java

public class Main { public static void main(String[] args) { Bank b = new Bank(); new Thread(b,"女").start(); new Thread(b,"男").start(); } }

Bank1.java

public class Bank1 implements Runnable{ private int money = 500; private int count = 0; @Override public void run() { synchronized (this){ for (int i = 1; i < 6; i++) { if (count > 4){ System.out.println(Thread.currentThread().getName() +":第 "+ i + " : 次取款失败!"); }else{ System.out.println(Thread.currentThread().getName() +":第 "+ i + " : 次取款开始!"); synchronized (this){ money -= 100; count ++; } } } } } }``` ### Bank2.java ```java public class Bank implements Runnable{ private int money = 500; private int count = 0; @Override public void run() { for (int i = 1; i < 6; i++) { if (count > 4){ System.out.println(Thread.currentThread().getName() +":第 "+ i + " : 次取款失败!"); }else{ System.out.println(Thread.currentThread().getName() +":第 "+ i + " : 次取款开始!"); synchronized (this){ money -= 100; count ++; } } } } }

问题

Bank2 中取款的 次数 会比 Bank1 多一次,题目本意是 男女混合取款 5 次总计 500
Bank1 中外层的 synchronized 会使 先开始的进程一直取款无法交替取款

源题

张三和他的妻子各拥有一张一行卡和存折,可以对同一个银行账号进行取款的操作,现银行存款为 500 RMB,每人个取款 5 次,在取款中存在网络延迟,现 使用多线程模拟这个过程

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3195 引用 • 8215 回帖
  • synchronized
    3 引用 • 6 回帖
  • 线程
    122 引用 • 111 回帖 • 3 关注
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    9479 引用 • 43200 回帖 • 108 关注
1 操作
illn 在 2020-06-02 14:05:27 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • footmanff 1 赞同 via macOS

    Bank1:两个线程在同一个对象上加锁,内部的逻辑是顺序执行的,先开始的线程会进入临界区,完成 5 次取款。
    Bank2:两个线程都在循环内去争用一个锁,count 被加到 4 以后,两个线程同时进入 else 块,都会有第三次取款的日志,然后先后获取锁,对 count 做两次递增,最终加到 6,你可以 print 一下,就知道了。

    1 回复
  • 其他回帖
  • illn

    一种解法还没有理解

    private int out=500; private boolean flag = false; public void run() { while (!flag) { sale(); } } public synchronized void sale(){ if (out<=0) { System.out.println("余额不足已支付"+Thread.currentThread().getName()+"余额为:"+out); flag=true; return; } out = out-100; try { Thread.sleep(500);//延迟0.5秒 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"准备取钱"); System.out.println(Thread.currentThread().getName()+"取钱成功"); }
  • visus

    🐮币

  • illn

    谢谢,我再看看