多线程-03-线程安全问题

一、线程安全问题

  • 多个线程同时操作同一个共享资源的时候可能会出现业务安全问题,称为线程安全问题。

二、线程安全问题模型

取钱模型演示

  • 需求:小明和小红事一对夫妻,拥有共同账户,余额10万元
  • 如果小明和小红同时来取钱,而且2人都要取钱10万元,则会出现线程问题。
    在这里插入图片描述
    问题出现情况解释:
  • cpu执行线程任务:有可能先执行小明的线程,然后判断小明的线程任务1,查询的到结果是true。
  • 此时出现某种原因,cpu执行小红线程任务,然后判断小红的线程任务1,此时得到的结果也是true。
  • 此时假设小红线程继续执行,此时小红取到10万块钱。然后更新账户余额,此时的余额为0
  • 小红线程结束,小明线程继续执行,由于任务1的结果是true,此时小明也是可以取出10万块钱。更新余额,此时余额称为-10万元
  • 最后的记过就是两人都取了10万元,银行亏损10万元

在这里插入图片描述

三、线程安全问题出现的原因

  • 存在多线程并发
  • 同时访问共享资源
  • 存在修改共享资源

总结:多个线程同时访问同一个共享资源且存在修改该资源

四、取钱业务代码案例

定义一个账户类,里边创建取钱的方法

/**
 * @Author: {LZG}
 * @ClassName: Account
 * @Description: TODO
 * @Date: 2022/5/10 1:26
 **/
public class Account {
    private String cardId;
    private double money;


    public Account() {
    }

    public Account(String cardId, double money) {
        this.cardId = cardId;
        this.money = money;
    }
    public void drawMoney(double money) {
        //  1、先获取是谁来取钱,线程的名字是任命
        String name = Thread.currentThread().getName();
        //  2、判断账户是否购钱
        if (this.money>=money){
            //  3、取钱
            System.out.println(name+"来取钱成功,吐出:"+money);
            //  4、更新余额
            this.money-=money;
            System.out.println(name+"取钱后剩余:"+this.money);
        }else {
            //  余额不足
            System.out.println(name+"来取钱,余额不足!");
        }
    }


    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }


}

创建一个曲线的线程类

/**
 * @Author: {LZG}
 * @ClassName: DrawThread
 * @Description: 取钱的线程类
 * @Date: 2022/5/10 1:30
 **/
public class DrawThread extends Thread{
    private Account acc;

    public DrawThread(String name,Account acc) {
        super(name);
        this.acc = acc;

    }

    @Override
    public void run() {
        //  取钱的
        acc.drawMoney(100000);
    }
}


客户测试

/**
 * @Author: {LZG}
 * @ClassName: ThreadDemo1
 * @Description: TODO
 * @Date: 2022/5/10 1:28
 **/
public class ThreadDemo1 {
    public static void main(String[] args) {
        //  1、定义一个线程类,创建一个共享账户对象
        Account account = new Account("ICBC-001",100000);

        //  2、创建两个线程对象,代表小明和小红同时进来了
        new DrawThread("小明",account).start();
        new DrawThread("小红",account).start();
    }
}

运行结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值