一般使用synchronized的时候,主要是用在方法上,代码块上,当使用在代码块的时候一般锁的都是类或者对象,但是有的人会去锁封装的常量。这个时候去锁这个封装的常量就会有问题了,我们来写个简单的demo来看看什么问题。
错误使用案例:
public static void print(Integer num) {synchronized (num) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ":" + System.currentTimeMillis() / 1000);}}
当num为2的时候输出

没有问题对吧。
把num换成128输出:

这时候就有问题了都是单独运行的统一时间执行的,测试完后就会发现-128~127
范围的数字是锁住了,但是这个范围之外的没有锁住,是什么原因呢?下面就为你揭晓答案哦:
debug Integer num = 129;在valueOf上打断点后看到

初始化就会调用valueOf,如果在-128~127就会存缓存里面取,不在这个范围就会new 一个对象放进去,new 对象地址都不一样肯定是锁不住了呀。Long类型也是一样的

那如果你要锁一个常量怎么办呢?
可以转换为String锁字符串,前面加一个单独的标识拼接一下。错误的使用:
public static void print(Integer num) {String key = "NUM_KEY_" + num;synchronized (key) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ":" + System.currentTimeMillis() / 1000);}}
这样的你觉得可以锁住不?答案肯定锁不住的因为String拼接时候就是
new String的操作这样拼接后地址不一样了,导致锁不住。
一定要用常量的话,可以写成静态的,或者使用分布式锁等,
尽量避免锁这样的数字吧。还有就是Double,Float小数是一个都锁不住的哦。
文章同时会更新到公众号,觉得对你有帮助或者有用的可以关注一下哦

本文探讨了在Java中错误地使用`synchronized`关键字锁住封装的常量时可能出现的问题。当锁定的Integer数值在-128到127之间时,由于缓存机制,会锁住这部分范围,而超出该范围则无法实现同步。同样的问题也适用于Long类型。为了解决这个问题,建议使用静态常量或采取分布式锁方案,避免对小数进行锁定,因为它们无法被正确同步。
691

被折叠的 条评论
为什么被折叠?



