想问一个关于java8线程安全的问题

写了一个卖票的例子用synchronized结果每次是一个线程的名字在输出,虽然线程有随机性,但也不会每次都抢到吧。。。这是为什么呀

public class MyRunnable implements Runnable {
    private int ticket = 100;
    private Object object = new Object();
    public void run() {
        while (true) {
            synchronized (object) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":出售第" + (101 - ticket) + "张票");
                    ticket -= 1;
                } 
            }

        }
    }
}

//主函数
public class Main {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread t1 = new Thread(myRunnable,"窗口1");
        Thread t2 = new Thread(myRunnable,"窗口2");
        Thread t3 = new Thread(myRunnable,"窗口3");
        
        t1.start();
        t2.start();
        t3.start();
    }
}
阅读 1.7k
1 个回答

你的代码while(true)使得一个线程不停的获得CPU时间片去执行,然后睡眠是在获得锁后的,这个睡眠sleep并不会释放锁,导致其他线程根本没机会获得CPU时间片,也没法获得锁。

其中的run方法体建议改为如下:

 while (true) {
                synchronized (object) {
                    if (ticket > 0) {
//                        try {
//                            Thread.sleep(100);
//                        } catch (InterruptedException e) {
//                            e.printStackTrace();
//                        }
                        System.out.println(Thread.currentThread().getName() + ":出售第" + (101 - ticket) + "张票");
                        ticket -= 1;
                    }
                }
                try {
                    Thread.sleep(100);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题