Java [synchronized] 问题请教

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

先上 代码 后提问

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 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3190 引用 • 8214 回帖 • 1 关注
  • synchronized
    3 引用 • 6 回帖
  • 线程
    122 引用 • 111 回帖 • 3 关注
  • Q&A

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

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

相关帖子

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...
  • 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

    🐮币

  • footmanff 1 赞同

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

    1 回复
  • illn

    谢谢,我再看看