-1

myCode 如下:

我想知道为什么zhangsan和lisi都可以打印:李四9锁对象:1522503870 张三9锁对象:1522503870

public class TicketConsumer implements Runnable {
    private Integer i;

    public TicketConsumer(int i) {
        super();
        this.i = i;
    }

    @Override
    public void run() {
        while (true) {
           
            System.out.println(Thread.currentThread().getName() + i + "锁对象before:" + System.identityHashCode(i));
            
            synchronized (i) {
                System.out.println(Thread.currentThread().getName() + i + "锁对象:" + System.identityHashCode(i));
                if (i > 0) {
                    try {
                        Thread.sleep(100);    // 模拟抢票延迟
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "抢到了第" + i-- + "张票");
                } else {
                    return;
                }
            }
        }
    }

    public static void main(String[] args) {
        TicketConsumer ticket = new TicketConsumer(new Integer(10));
        Thread t1 = new Thread(ticket, "张三");
        Thread t2 = new Thread(ticket, "李四");
        t1.start();
        t2.start();
    }
}

结果是:

张三10锁对象before:1417180225
李四10锁对象before:1417180225
张三10锁对象:1417180225
张三抢到了第10张票
张三9锁对象before:1522503870
李四9锁对象:1522503870
张三9锁对象:1522503870
李四抢到了第9张票
李四8锁对象before:2045992545
李四8锁对象:2045992545
张三抢到了第9张票

我想知道为什么张三和李四都可以得到:李四9锁对象:1522503870 张三9锁对象:1522503870

4

1 回答 1

0

我可能错了,但是当您执行 i-- 时,您可以看到 System.identityHashCode(i) 发生了变化,因此在同步块外等待的另一个线程现在可以进入它。在更改身份/引用的对象上同步不是一个好主意,请尝试在堆栈上同步并使用 stack.push(...) 进行调试:这不会更改引用。

于 2022-01-14T11:49:04.950 回答