如何解决多线程不安全的问题

        举个生活比较常见的例子,咱们生活中过年回家的时候常常会出现需要抢票的情况,然后有一些平台会帮助我们代抢票的服务,这个时候往往会出现多个平台抢票的情况,其实这就是多线程的一种应用,我们先按照常规多线程实现一下

代码如下

public class Ticket extends Thread {
    static int total=10;//这里的static是为了共享数据,因为有多个对象,不然会出现30张票,
    static int buy=0;
    @Override
    public void run() {//模拟购票
        while(total>0){
            total--;
            buy++;
            System.out.println("已卖"+buy+"张票,剩余"+total);
        }
    }
    public static void main(String[] args) {
        Ticket t1=new Ticket();
        t1.setName("携程");
        Ticket t2=new Ticket();
        t2.setName("飞猪");
        Ticket t3=new Ticket();
        t3.setName("12306");
        t1.start();
        t2.start();
        t3.start();
    }
}

乍一看好像么有什么逻辑性的错误,但是一运行问题就来了

我们会发现出现了数据混乱的问题 

原因其实是就是一个线程还没有结束的时候,第二个线程就已经抢占进来了,我门来画个图可能会好懂一点

图画的有一点丑,请见谅,如上图第一个线程刚刚使用方法准备返回9,1的时候,第二个线程就在第一个线程回来的途中,开始占用方法,这时候第二个线程就会返回8,2,而第一个线程这时候还没有成功打印,这样第二个线程就会返回一个错误的信息,造成数据的混乱,也就是咱们常说的多线程安全问题; 

那咱们如何解决呢?

方法就是把读取和返回绑定起来,当成一个完整的过程,这里咱们可以用synchronized()这个方法来实现,它的作用相当于一把锁,把读取和返回锁起来,实现线程信息的完整

代码实现如下

这里要注意synchronized()括号中不能用this,一定要用Ticket.class,因为这里三个对象,都要使用循环里面的方法

public class Ticket extends Thread {
    static int total=100;
    static int buy=0;
    @Override
    public void run() {//模拟购票

            while (total > 0) {

                synchronized (Ticket.class) {
                    if (total<=0){return;}
                    --total;
                    ++buy;
                    System.out.println(Thread.currentThread().getName()+"已卖" + buy + "张票,剩余" + total);
                }
            }
    }
    public static void main(String[] args) {
        Ticket t1=new Ticket();
        t1.setName("携程");
        Ticket t2=new Ticket();
        t2.setName("飞猪");
        Ticket t3=new Ticket();
        t3.setName("12306");
        t1.start();
        t2.start();
        t3.start();
    }
}

最终的运行结果如下

 当然这里的synchronized()方法不一定要放在循环里面,也可以构造buy方法,然后放在访问修饰符前面或者访问修饰符和返回类型的之间

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值