关于Synchronized关键字的疑问

来源:9-1 死锁

寒暄丶

2019-01-09

昨天在工作中碰到这么一种情况,用户每个月消费1000返100,在每个月初结算并在app上弹窗供用户点击领取,这里因为涉及并发问题所以考虑到可用的操作,觉得synchronized(项目jdk1.7)比较快捷有效。
当时采用synchronized锁住的是在该类中创建的静态对象,但是实测发现,只要疯狂点领取按钮/Jmeter 0秒多线程压测,还是会发生多次领取到的情况!!
图片描述
1.这里就产生一个问题,这是否可以证明死锁这个例子的synchronized选择锁住的静态对象但还是线程不安全的呢?
于是对synchronized关键字锁住的东西再次感到有些迷茫,早上在网上找到一篇简书是这么一个表格:

图片描述
和这么一段话:
图片描述

2.上述陈述的结论我是这么理解的:既然用到了synchronized,就应该保证锁住的东西是类对象,否则都是线程不安全的。

但是这个想法我用synchronized修饰了方法又测试发现不会出现多次领取的情况,而且用简书文章末尾的方法就是synchronized修饰类对象依然会出现多次领取的情况!!!真的感觉很困扰很混乱

麻烦老师帮忙分析解答一下,多谢老师!!!!!

(这是此篇简书的链接https://www.jianshu.com/p/d53bf830fa09 侵删)

写回答

2回答

Jimin

2019-01-09

你好,这样理解确实有点问题,理论上使用synchronized的话,同步的具体范围是开发自己选的,核心是锁最关键的共享资源,而且要尽可能小。有一点需要明确,许多可以辅助做到线程安全的类,使用不当的话,也会造成线程不安全,比如课程里演示的vector删除
synchronized支持多种类型的同步,每一种同步都明确了自己的锁范围,这个需要开发人员选择最合适的,可以锁类对象也可以锁实例对象,虽然锁类对象可以完全保证线程安全,但不代表只能使用这种,因为代价最大,我们实际中要尽可能的减小锁的程度。但是如果锁实例对象解决不了根本问题,那么锁类对象也是必须的。
这两种锁操作本身都是线程安全的,而不能因为错用就说锁对象实例是线程不安全的,这只能说明那种场合不适合锁实例对象,因为synchronized确实已经锁住了实例对象。

0
7
寒暄丶
非常感谢!
2019-01-09
共7条回复

寒暄丶

提问者

2019-01-09

用了ConcurrentHashMap缓存 + 延时线程池(定时清缓存) + synchronized关键字修饰静态Object的方式暂时解决了这个问题  果然理论还是得自己实践才能慢慢来体会吧.. 还是自己没理清,还是很感谢有老师的知道~

0
0

Java高并发编程,构建并发知识体系,提升面试成功率

构建完整并发与高并发知识体系,倍增高薪面试成功率!

3923 学习 · 832 问题

查看课程