关键字synchronized 保证同一时刻,只有一个线程执行某一个方法或代码块
- 当一个对象被一个线程修改时,可以阻止其他线程看到其内部的不一致状态
- 正确的使用同步可以避免任何对象看到其不一致状态
不仅于此,
- 没有同步,各个线程之间对象的变化是相互不感知的
- 进入的各个线程都能看到,同一个锁保护的之前所有的修改信息
- 就是说不同步,别的线程改变对象值,本线程不一定何时能看到修改后的值
Java 语言规范保证读或者写一个变量(除了long、double)是原子的
为了提升性能,在读写原子数据的时候,不使用同步也是很危险的
- 因为一个线程写入的值,对于另一个线程不一定是可见的
- 为了线程之间可靠的通信,为了互斥访问,同步是必要的
不要使用Thread.stop 方法,线程不安全
- boolean是原子读写的,不需要加锁
- 但是这段代码是不会停止的
- 问题在于:由于没有同步,不能保证后台线程合适能看到这个boolean变量
- 没有同步,虚拟机把代码优化成:
---->
- 加上同步域,可满足一秒左右停止线程
- 如上看到,读写方法都被同步
- 如果读写操作没有都被同步,仅仅同步写操作,同步是不会起作用的
- 同步仅仅为了通信效果,因为读写是原子的
第三个版本,使用volatile 关键字:
- volatile 不提供互斥访问
- 每次写入都会写入主存,其他线程及时可见
- 使用volitale 产生序列号,请小心::
- 这里的 a++ 操作不是原子的,获得的结果可能会有问题
- 可以考虑使用原子包
最佳办法:
- 要么不共享可变数据,要么共享不可变数据
- 尽量将可变数据,限制在一个线程内
- 安全发布对象引用
- 静态域、volitale、final、锁定的访问域、放到并发的集合中
当多个线程共享可变数据的时候,读和写都需要同步
- 同步做了两件事:
- 及时通知其他线程
- 互斥访问
- 会造成活性失败和安全性失败
- 如果仅仅需要线程间交互通信,不需要互斥访问:请使用volitale