本文共 1242 字,大约阅读时间需要 4 分钟。
一般使用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小数是一个都锁不住的哦。
文章同时会更新到公众号,觉得对你有帮助或者有用的可以关注一下哦
转载地址:http://cgfnn.baihongyu.com/