3.多线程的并发问题

2018-05-18  本文已影响0人  xialedoucaicai

多线程在提高运行效率的同时,也带来了并发问题,所谓并发问题就是多线程操作共享资源,导致数据状态异常。
以买票为例,10个人登录了12306,但余票只有5张。

  1. 初始状态有5张票,用户1来买,余票为5,付钱准备出票
  2. 这时用户2也来买,由于票还没出,所以查询发现余票仍未5,付钱准备出票
  3. 此时用户1出票,余票减一变为4
  4. 用户2也出票了,余票减一也变为了4

问题就出在这里,现在实际只有3张票,但余票却显示为4张,余票作为一个共享资源,因为多线程,导致状态异常了,运行下列代码,会发现余票最终成为了负值。

代码示例:

public class Ticket {
    public int total = 5;
    
    public void buy() throws InterruptedException{
        if(total > 0){
            //模拟中间过程
            Thread.sleep(100);
            --total;
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        Ticket ticket = new Ticket();
        TicketThread ticketThread = new TicketThread(ticket);
        //10个人抢5张票
        for(int i=0;i<10;i++){
            new Thread(ticketThread).start();
        }
        //确保所有线程都执行完了
        Thread.sleep(3000);
        System.out.println("剩余:"+ticket.total);
    }
}
public class TicketThread implements Runnable{
    Ticket ticket = null;
    public TicketThread(Ticket ticket) {
        this.ticket = ticket;
    }
    
    @Override
    public void run() {
        try {
            ticket.buy();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

那如何解决这个问题呢?我们可以为buy()方法加上synchronized关键字,保证某一时刻只能有一个线程在执行buy()方法,这就相当于让多线程排队,强制变成了单线程,这样就可以解决并发问题了。下一节我们将更细致的探讨synchronized关键字。

上一篇 下一篇

猜你喜欢

热点阅读