java多线程资源共享线程分配问题

问题:
开两个优先级相同的线程处理同一对象的一个属性ticket,第一次运行时Thread-0操作ticket=5,但是却在最后被打印出来,并且线程分配也不是1:1的(尝试过将ticket改为50也会出现48个Thread-1,2个Thread-0的情况),而在第二次运行时很正常,这是为什么?

源码:
class MyThread implements Runnable{

private int ticket = 5;
public void run(){
    for( int i = 0; i < 100; i ++ ){
        if( ticket > 0 )
            System.out.println( Thread.currentThread().getPriority()+ "   "+ 
                Thread.currentThread().getName()+ "   "+ ticket--);
    }
}

}
public class CurrentThreadDemo{

public static void main(String args[]){
    MyThread my1 = new MyThread();
    //MyThread my2 = new MyThread();
    Thread t1 = new Thread(my1);
    Thread t2 = new Thread(my1);
    t1.start();
    t2.start();
}

}

问题截图:
图片描述

阅读 3.2k
2 个回答

首先,写法有问题,两个线程用同一个资源,必须保证资源是线程安全的,应该用:

private AtomicInteger ticket = new AtomicInteger(5);

public void run() {
    ...
    System.out.println(ticket.getAndDecrement());
}

其次,你无法保证两个线程的运行速度,可能1个线程做了51次(如果ticket初始值是100的话),另一个线程做了49次;也有极端情况,一个线程做了100次,另一个线程1次也没做到。

一般来说,这么写的话:

t1.start();
t2.start();

线程t1会比线程t2先做(这并不意味着t1做的次数会比t2多),但也非绝对。

我觉得这两个结果都是正常的。线程的调度顺序是你无法预测的,即使相同的优先级的线程也不会一定会有占有相同的cpu资源。线程在切换时会有上下文切换的代价,有时候jvm为了提高效率,会减少线程切换。

上述情况可能是因为:thread-0可能先占有了5,但是还没来得及打印,cpu被占用,thread-1就开始打印了。所以顺序不一致。

还有ticket--不是原子性的操作,我觉得甚至可能出现两个线程打印重复数字的可能性。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题