请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于Synchronized关键字的疑问

昨天在工作中碰到这么一种情况,用户每个月消费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 09:57:55

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

0 回复 有任何疑惑可以回复我~
  • 提问者 寒暄丶 #1
    那您觉得这种情况下用synchronized应该如何处理呢(前面又测出synchronized修饰方法也就是锁实例对象确实也是线程不安全的)您的意思是锁类对象肯定是线程完全安全的  但是我修饰了.class类对象  还是出现多次领取的情况...  脑子感觉一团浆糊...    需要多试试..
    回复 有任何疑惑可以回复我~ 2019-01-09 10:00:46
  • 提问者 寒暄丶 #2
    您觉得在这样的场合中是否需要在方法中sleep一下比较合适呢
    回复 有任何疑惑可以回复我~ 2019-01-09 10:07:32
  • xxxxxxx_2 回复 提问者 寒暄丶 #3
    你的数据幂等性确定没问题吗
    回复 有任何疑惑可以回复我~ 2019-01-09 11:53:22
提问者 寒暄丶 2019-01-09 15:22:55

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

0 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信