为了账号安全,请及时绑定邮箱和手机立即绑定

JAVA中多线程读取成员变量的重复问题

JAVA中多线程读取成员变量的重复问题

慕无忌1623718 2019-04-25 10:19:28
这是个模拟卖票的问题,使用一个对象实现Runnable接口建立四个线程,这个对象有100张票,四个进程同时卖,因为没使用锁,所以会出现负数票,但是为什么会出现相同的票呢?8号票卖了四次,是因为成员变量在if之后进栈保存了值?然后直接用这个num输出吗?代码: class Ticket implements Runnable//extends Thread {     private int num = 100       public void run()//这时不能抛出异常,因为覆盖的原函数没有抛出异常,必须catch     {         while(true)         {             if(num>0)             {                 try{                     Thread.sleep(2);                 }                 catch(InterruptedException e){}                 System.out.println(Thread.currentThread().getName()+" sale "+num--);             }             else break;         }     } } class Demo {     public static void main(String[] args) {         Ticket t=new Ticket();         Thread t1=new Thread(t);         Thread t2=new Thread(t);         Thread t3=new Thread(t);         Thread t4=new Thread(t);         t1.start();         t2.start();         t3.start();         t4.start();     } }部分输出Thread-1 sale 12 Thread-0 sale 13 Thread-0 sale 10 Thread-1 sale 9 Thread-3 sale 9 Thread-2 sale 10 Thread-2 sale 8 Thread-1 sale 8 Thread-0 sale 8 Thread-3 sale 8 Thread-2 sale 7 Thread-1 sale 6 Thread-0 sale 5 Thread-3 sale 4 Thread-2 sale 3 Thread-1 sale 2 Thread-0 sale 1 Thread-3 sale 0 Thread-2 sale -1 Thread-1 sale -2
查看完整描述

3 回答

?
噜噜哒

TA贡献1784条经验 获得超7个赞

System.out和num--是两个操作(而且这两个操作还不是原子操作,但这里先看成原子操作,比较好解释),那么,System.out输出数字后在还没num--时线程被抢占,抢占成功的另一个线程也执行到System.out,但是依旧还没执行num--,又被另一个线程抢占,以此类推,就可能得到4个8了


查看完整回答
反对 回复 2019-05-06
?
函数式编程

TA贡献1807条经验 获得超9个赞

由于没有使用同步锁,导致多个线程存在同时访问num变量,可以将关键代码改成这样:

while (true) {
    synchronized (this) {
        if (num > 0) {
            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
            }
        } else {
            break;
        }
        System.out.println(Thread.currentThread().getName() + " sale " + num--);
    }

}


查看完整回答
反对 回复 2019-05-06
  • 3 回答
  • 0 关注
  • 518 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信