java多线程重复卖票的问题

来源:互联网 发布:查询某一列重复的数据 编辑:程序博客网 时间:2024/05/21 22:55
上代码:
public class Test {public static void main(String[] args) {        ThreadTicket ticket = new ThreadTicket();        Thread t1 = new Thread(ticket);         Thread t2 = new Thread(ticket);         t1.start();        t2.start();    }}class ThreadTicket implements Runnable {    int ticket = 10;    @Override    public void run() {while(true) {if(ticket>0) {try {Thread.currentThread();Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"卖。。。"+ticket--);               } else {break;}}    }}
运行结果:
Thread-1卖。。。10Thread-0卖。。。10Thread-0卖。。。9Thread-1卖。。。8Thread-1卖。。。7Thread-0卖。。。6Thread-0卖。。。4Thread-1卖。。。5Thread-0卖。。。3Thread-1卖。。。2Thread-1卖。。。1Thread-0卖。。。0

问题:偶尔会出现重复卖票的情况,显示这在开发中是不允许的

原因分析:java中的原子性操作,是指读和写是原子性的,比如 i=5,这就是一个原子性的操作。多线程执行的时候,只能在一个原子操作力,才会没有并发读或并发写的情况。

通常情况下,在java里面,i++或者i--不是线程安全的,这里面有三个独立的操作:获得变量当前的值,为该值+1或者-1,然后写回新的值。

在没有额外资源可以利用的情况下,只能使用加锁才能保证读-改-写这三个操作是原子性的,这就是为什么会出现一定数量重复卖票的情况

另外,sleep()中指定的时间是线程不会运行的最短时间,因此,sleep()方法不能保证该线程睡眠到期后就开始执行,所以,加上sleep()以后,就增加了并发操作ticket()的机会,出现重复卖票的可能性也会增加

修改后代码:

class ThreadTicket implements Runnable {    int ticket = 10;    @Override    public void run() {synchronized (this) {while(true) {if(ticket>0) {try {Thread.currentThread();Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"卖。。。"+ticket--);               } else {break;}}}    }}
运行结果:
Thread-0卖。。。10Thread-0卖。。。9Thread-0卖。。。8Thread-0卖。。。7Thread-0卖。。。6Thread-0卖。。。5Thread-0卖。。。4Thread-0卖。。。3Thread-0卖。。。2Thread-0卖。。。1




1 0
原创粉丝点击