java多线程加synchronized锁后变为单线程

问题遇到的现象和发生背景

复习多线程的时,在模拟窗口卖票场景发现加上线程锁之后只有一个窗口在出售票。不加线程锁时三个窗口都可以买票但是卖出的票可能重复或有票没有售出。

问题相关代码
public class runableImpl implements Runnable {

    private Object object = new Object();
    private int ticket = 0;

    @Override
    public void run() {
        synchronized (object) {
            try {
                Thread.sleep(100);
                while (true) {
                    if (ticket >= 100) {
                        return;
                    }
                    ticket++;
                    System.out.println(Thread.currentThread().getName() + ":抢到第" + ticket + "张票");
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

//测试
class TestRunable {
    public static void main(String[] args) {
        runableImpl runable = new runableImpl();
        Thread thread = new Thread(runable, "窗口001");
        Thread thread2 = new Thread(runable, "窗口002");
        Thread thread3 = new Thread(runable, "窗口003");
        thread.start();
        thread2.start();
        thread3.start();
    }
}

运行结果及报错内容

上述代码结果为同一个窗口售出了所有票。第一张票是由谁卖出,就会由这个窗口把票卖完。

img

我的解答思路和尝试过的方法

我尝试增加票数和睡眠时间但是都是同一个窗口卖完的票。三个线程谁先进入方法就会由这个线程把票卖完。

我想要达到的结果

一百张票由多个线程一起售卖,并且没有重复票售出或漏出售票。

改成这样

public class RunnableImpl implements Runnable {
    private Object object = new Object();
    private int ticket = 0;

    @Override
    public void run() {
            try {
                while (true) {
                    Thread.sleep(100);
                    synchronized (object) {
                        if (ticket >= 100) {
                            return;
                        }
                        ticket++;
                        System.out.println(Thread.currentThread().getName() + ":抢到第" + ticket + "张票");
                    }
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    }
}

因为你把锁加在sleep外面了,把整个逻辑都锁住了
你应该加在最核心的部分