sjk1996 2018-10-04 19:45 采纳率: 0%
浏览 1007

java synchronized修饰的方法中调用sleep竟然产生这样的输出?!

 package com.imooc.bank;

//银行类
public class Bank {
    private String account;
    private int balance;

    public Bank(String account, int balance) {
        this.account = account;
        this.balance = balance;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public int getBalance() {
        return balance;
    }

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

    @Override
    public String toString() {
        return "Bank [账号:"+account+", 余额:"+balance+"]";
    }

    //存款
    public synchronized void saveAccount() {
        int balance = getBalance();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        balance += 100;
        setBalance(balance);

        System.out.println("存款后的账户余额为:"+balance);
    }

    //取款
    public void drawAccount() {
            int balance = getBalance();

            balance -= 200;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            setBalance(balance);

            System.out.println("取款后的账户余额为:"+balance);

    }



}
 package com.imooc.bank;
 //取款线程

public class DrawAccount implements Runnable{

    private Bank bank;

    public DrawAccount(Bank bank) {
        this.bank = bank;
    }

    @Override
    public void run() {
        bank.drawAccount();
    }


}
 package com.imooc.bank;
//存款线程
public class SaveAccount implements Runnable{

    private Bank bank;

    public SaveAccount(Bank bank) {
        this.bank = bank;
    }

    @Override
    public void run() {
        bank.saveAccount();

    }


}

 package com.imooc.bank;
//测试类
public class Test {

    public static void main(String[] args) {
        Bank bank = new Bank("1001", 1000);

        SaveAccount sa = new SaveAccount(bank);
        DrawAccount da = new DrawAccount(bank);

        Thread save = new Thread(sa);
        Thread draw = new Thread(da);

        save.start();
        draw.start();

        try {
            save.join();
            draw.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //加join是为了让下面这条语句最后输出
        System.out.println(bank);

    }

}

为啥会产生这样的输出?
取款后的账户余额为:800
存款后的账户余额为:1100
Bank [账号:1001, 余额:1100]

如果我把saveAccount方法也用synchronized修饰的话就会正常输出。
存款后的账户余额为:1100
取款后的账户余额为:900
Bank [账号:1001, 余额:900]

是sleep的原因导致调用这个public synchronized void saveAccount() 方法的线程被阻塞, 然后被别的线程占用了cpu吗?
不是说synchronized修饰的方法调用过程中不会被别的线程打断吗?
求大神解答!!

展开全部

  • 写回答

4条回答 默认 最新

  • zhuofai_ 2018-10-05 05:33
    关注

    由结果分析就能看出来了啊!
    第一步首先你先save.start();然后再开启线程draw.start();并不是一起开的线程,程序顺序执行的是
    第二步那么我们为什么会得出"取款后的账户余额为:800 存款后的账户余额为:1100"这个结果呢?
    * 结果显示我们的程序首先运行的是取款操作,然后执行的才是存款操作.
    * 那么我们就可以得出结论,是因为存款操作加锁导致进入程序变慢,
    * 也就是说,存款线程首先要先获取锁,而取款线程可以直接运行取款操作没有任何阻碍
    第三步那么为什么结果余额会是800 和 1100呢?
    * 这是因为开启线程进入run方法拿到的是同一个bank对象此时进入到save和draw我还是画图给你看好了图片说明

    评论
  • threenewbee 2018-10-04 21:25
    关注

    不是不会被打断,而是多个线程同时调用同一个方法,才会同步,别的线程调用别的代码,不会。

    评论
  • 暖酒与春风 2018-10-07 18:06
    关注

    这是很明显的线程安全问题,因为加减操作是非原子操作,所以多线程中不加锁的话会出现脏读的情况,其实你加不加sleep这种问题都会出现,加了sleep
    只会比较容易出现而已

    评论
  • 不羁_弓虽 2018-10-07 21:51
    关注

    这个应该和cpu处理有关系,两个线程同时开启,让他们两个同时进行开始,看他们两个谁运气好。就像抢火车票一样,有的能抢到,有的抢不到。这只是打个比方,希望你能理解。

    评论
编辑
预览

报告相同问题?

悬赏问题

  • ¥30 matlab ode45 未发现警告,但是运行出错
  • ¥15 vscode platformio
  • ¥15 代写uni代码,app唤醒
  • ¥15 全志t113i启动qt应用程序提示internal error
  • ¥15 ensp可以看看嘛.
  • ¥80 51单片机C语言代码解决单片机为AT89C52是清翔单片机
  • ¥60 优博讯DT50高通安卓11系统刷完机自动进去fastboot模式
  • ¥15 minist数字识别
  • ¥15 在安装gym库的pygame时遇到问题,不知道如何解决
  • ¥20 uniapp中的webview 使用的是本地的vue页面,在模拟器上显示无法打开
手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部