使用synchronized小坑

一般使用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小数是一个都锁不住的哦。

 

                                         文章同时会更新到公众号,觉得对你有帮助或者有用的可以关注一下哦 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值