Java synchronized遇到的坑

 当两个线程使用synchronized同步两个类型和值都相同的final变量时,神奇的一幕发生了,这两个锁变成了同一把锁!子线程先获取到锁0后,主线程获取锁1阻塞了,直到子线程释放锁0主线程才获取到锁1!两个线程“被”同步了!

    private final Boolean lock0 = true;
    private final Boolean lock1 = true;

    private void syncTest() throws InterruptedException {
            new Thread(() -> {
                try {
                    log.info("child try lock 0");
                    synchronized (lock0) {
                        log.info("child lock 0");
                        Thread.sleep(1000);
                    }
                    log.info("child unlock 0");
                } catch (Exception e) {
                    log.error("", e);
                }
            }).start();

            Thread.sleep(100);
            log.info("main try lock 1");
            synchronized (lock1) {
                log.info("main lock 1");
            }
            log.info("main unlock 1");
    }

以上代码输出为

2022-04-11 16:36:08.998  INFO 4924 --- [       Thread-2] child try lock 0
2022-04-11 16:36:08.998  INFO 4924 --- [       Thread-2] child lock 0
2022-04-11 16:36:09.097  INFO 4924 --- [           main] main try lock 1
2022-04-11 16:36:09.998  INFO 4924 --- [       Thread-2] child unlock 0
2022-04-11 16:36:09.998  INFO 4924 --- [           main] main lock 1
2022-04-11 16:36:09.998  INFO 4924 --- [           main] main unlock 1

若把lock1改为false,则正常,输出为

2022-04-11 16:41:51.330  INFO 22512 --- [       Thread-2] child try lock 0
2022-04-11 16:41:51.330  INFO 22512 --- [       Thread-2] child lock 0
2022-04-11 16:41:51.430  INFO 22512 --- [           main] main try lock 1
2022-04-11 16:41:51.430  INFO 22512 --- [           main] main lock 1
2022-04-11 16:41:51.430  INFO 22512 --- [           main] main unlock 1
2022-04-11 16:41:52.330  INFO 22512 --- [       Thread-2] child unlock 0

我猜测jvm把两个类型和值都相同的final变量优化为同一个对象,这样使用synchronized同步这两个变量时,实际为同步同一个变量,导致两个线程同步。打印log.info("{}", lock0 == lock1);输出为true,证明猜测。

若把两个锁变量换成Object类型时,编译器不会优化为同一个对象,我猜测编译器的这个优化只针对基本类型。所以使用synchronized同步变量时,尽量别使用基本类型变量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值