同步代码块处理线程的安全问题(实现Runnable接口)

拿近期抢茅台的例子来说吧,天猫超市今天一共有100瓶茅台,但是有1万人抢购,假如我们把每个人的抢购当作一个线程来说,那么咱们实现一下抢茅台的代码:当然,下面的实现是不考虑线程的安全问题的。
首先先抽象一下抢茅台:
定义一个名字为Windows1的类,让所有用户都通过这个窗口去抢:

public class Windows1 implements Runnable {
    //初始化的时候给茅台定义100瓶的常量,不再改变
    private  int sum = 100;

    public void run() {
        System.out.println("开始抢购茅台");
        while(true){
            if (sum>0){
                //打印抢到的信息
                System.out.println(Thread.currentThread().getName()+":  抢购了一瓶剩下:"+sum+"瓶");
                //每抢到一瓶就剪减去一瓶
                sum--;
            }else{
                //没有了就跳出循环
               break;
            }
        }
    }
}

由于是实现了Runnable的接口创建的线程,所以在main函数中我们这样去处理:

public class MainStart {
    public static void main(String[] args) {
        //创建实体对象
        Windows1 windows1 = new Windows1();
        //实体对象当作参数传给Thread构造方法
        //我们当前先设置这三个人抢,当然你可以写100行,假设是100个人抢
        Thread thread = new Thread(windows1);
        Thread thread2 = new Thread(windows1);
        Thread thread3 = new Thread(windows1);
        //开始抢的动作,线程的激活
        thread.start();
        thread2.start();
        thread3.start();


    }
}

这样我们创建了三个窗口,也就是三个线程,让他们都去抢茅台,但是运行起来看一下结果:
在这里插入图片描述
一共100瓶,第100瓶被2个人抢走了,这两个人都抢到了编码为100号的茅台,最后这酒给谁那?这时候就要考虑线程的安全问题:

解决线程的安全问题(同步代码块)

这里要引入一个关键字:synchronized
使用结构是这样的:
加这个锁的让代码变为这样的执行流程:
每当有线程A进来要执行同步代码体的时候,就要去判断同步代码体的代码是不是有其他线程在执行,如果有其他线程在执行的话,线程A需要等执行的线程结束,才有可能轮到线程A执行,为什么是有可能,因为线程的执行需要CPU去分配,具体到谁是不确定的。
特别解释一下锁:任何类的对象都可以充当锁去使用,但是多个线程必须用同一把锁,也就是同一个对象,也就是只能让这个对象new一次。

synchronized (){
需要同步代码体,这里要理解,为了解决100瓶卖2次的问题,我们要把目标卖出的逻辑,也就是这100瓶的变换的代码当作同步代码体来处理。
}

用线程的方式实现抢100瓶茅台

public class Windows1 implements Runnable {
    //初始化的时候给茅台定义100瓶的常量,不再改变
    private int sum = 100;
    Object obj = new Object();
    public void run() {
        System.out.println("开始抢购茅台");
        while (true) {
            synchronized (obj) {
                if (sum > 0) {
                    //打印抢到的信息
                    System.out.println(Thread.currentThread().getName() + ":  抢购了一瓶剩下:" + sum + "瓶");
                    //每抢到一瓶就剪减去一瓶
                    sum--;
                } else {
                    //没有了就跳出循环
                    break;
                }
            }
        }
    }
}

mian函数和上面是一样的,同步的结果如下所示:
在这里插入图片描述

如果锁用的不是同一个对象的情况

在这里插入图片描述
所以要保证多线程的锁用的是一个对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangguan96

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值