线程安全的恰当定义:当多个线程访问同一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的。
根据线程安全的“安全程度”由强至弱排序,Java语言中各种操作共享的数据分为5类
1、不可变:final修饰的变量、String等
2、绝对线程安全:满足上述定义
3、相对线程安全:保证对对象的单独操作是线程安全的,调用时无需额外的同步手段,但对于特定顺序的连续调用手段,需要在调用端添加额外的同步手段。Vector、HashTable等。单独的方法都是synchronized,即多个线程执行同一个方法,必须是阻塞的;但多个线程执行不同的方法,例如一个add,一个remove,则是同时进行,会出现错误。
4、线程兼容:对象本身并不是线程安全的,但可以在调用端正确使用同步手段来保证安全使用,如ArrayList、HashMap。
5、线程对立:
线程安全的实现方法:
同步的定义:在多个线程并发访问共享数据时,保证共享数据在同一时刻只被一个(或一些,使用信号量的时候)线程使用。
线程安全方法 | Java语言 | JVM实现 |
---|---|---|
互斥同步(阻塞同步) |
|
|
非阻塞同步 | CAS操作。Unsafe类,不提供给用户程序调用,可以通过反射或通过其他Java API间接使用,如JUC包中的AtomicInteger类方法使用了Unsafe类的CAS操作 | 硬件指令集的进步,CAS只通过一条处理器指令完成,实现操作和冲突检测的原子性 |
无同步方案 | 可重入代码 线程本地存储? |
锁优化
- 自旋锁与自适应自旋锁
- 锁消除
- 锁粗化
- 轻量级锁
- 偏向锁
问题:同步机制可以保证线程安全,有些代码天生就是线程安全的,不需要同步也能保证安全。锁是同步机制的一种吗?以上的锁优化是针对锁做的,锁到底是什么呢?在底层,指的就是对象头、Mark Word、锁的计数器等的操作?同步机制有些用到锁,有些没有用到锁?