同步访问共享的可变数据(66)

关键字synchronized 保证同一时刻,只有一个线程执行某一个方法或代码块

  • 当一个对象被一个线程修改时,可以阻止其他线程看到其内部的不一致状态
  • 正确的使用同步可以避免任何对象看到其不一致状态

不仅于此,

  • 没有同步,各个线程之间对象的变化是相互不感知的
  • 进入的各个线程都能看到,同一个锁保护的之前所有的修改信息
    • 就是说不同步,别的线程改变对象值,本线程不一定何时能看到修改后的值

Java 语言规范保证读或者写一个变量(除了long、double)是原子的

为了提升性能,在读写原子数据的时候,不使用同步也是很危险的

  • 因为一个线程写入的值,对于另一个线程不一定是可见的
  • 为了线程之间可靠的通信,为了互斥访问,同步是必要的

不要使用Thread.stop 方法,线程不安全

  • boolean是原子读写的,不需要加锁
  • 但是这段代码是不会停止的

22f25a7d70b1628a85006ef82c858a8a81a.jpg

  • 问题在于:由于没有同步,不能保证后台线程合适能看到这个boolean变量
  • 没有同步,虚拟机把代码优化成:

87f6a2cdee5f02b7c198047dcd5045e6cb8.jpg---->43e880237a7ab2f413a042fd5706179fc59.jpg

  • 加上同步域,可满足一秒左右停止线程

6de08d35602603ce958b1d26a860435bea2.jpg

  • 如上看到,读写方法都被同步
    • 如果读写操作没有都被同步,仅仅同步写操作,同步是不会起作用的
    • 同步仅仅为了通信效果,因为读写是原子的

第三个版本,使用volatile 关键字:

  • volatile 不提供互斥访问
  • 每次写入都会写入主存,其他线程及时可见

3262660d1d2ea8cbad1226f27b0309dc3d2.jpg

cdf1ad8b6b61f1185b965102a9059f307b5.jpg

  • 使用volitale 产生序列号,请小心::
    • 这里的 a++ 操作不是原子的,获得的结果可能会有问题

947a7a643ec748214021704dc98963f1c06.jpg

  • 可以考虑使用原子包

27ae8ab8c8151045af80fd0b5a498a239b5.jpg

最佳办法:

  • 要么不共享可变数据,要么共享不可变数据
  • 尽量将可变数据,限制在一个线程内 
  • 安全发布对象引用
    • 静态域、volitale、final、锁定的访问域、放到并发的集合中

当多个线程共享可变数据的时候,读和写都需要同步

  • 同步做了两件事:
    • 及时通知其他线程
    • 互斥访问
  • 会造成活性失败和安全性失败
  • 如果仅仅需要线程间交互通信,不需要互斥访问:请使用volitale

转载于:https://my.oschina.net/u/3847203/blog/2987594

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值