线程安全

Java中各种操作共享数据按照线程安全的安全程度由强至弱分为不可变绝对线程安全相对线程安全线程兼容线程对立

不可变

不可变的对象一定是线程安全的,只要一个不可变对象被正确构建,没有this引用逃逸,其外部可见状态永远不会改变;Java中符合不可变要求的类型:java.lang.String枚举类型java.lang.Number的部分子类(如LongDouble等数值包装类型BigIntegerBigDecimal等大数据类型),同为Number子类型的原子类AtomicIntegerAtomicLong非不可变

若共享数据是基本数据类型,只要在定义时使用final关键字修饰就可以保证是不可变的;

若共享数据是一个对象,保证对象的行为不会对其状态产生任何影响,保证对象行为不影响自己状态的途径有很多种,最简单的方式是将对象中带有状态的变量声明为final

绝对线程安全

一个类要达到不管运行时环境如何,调用者不需要任何额外同步措施通常需要付出很大的代价;Java中标注自己是线程安全的类大多数都不是绝对线程安全的。

代码示例待补充……

相对线程安全

通常意义上的线程安全,它保证对这个对象单独操作是线程安全的,调用时不需要做额外的保障措施,但对一些特定顺序的连续操作,就可能需要在调用端使用额外的同步手段来保证调用的正确性。大部分线程安全的类属于这种类型,例如:VectorHashTableCollectionssynchronizedCollection()方法包装的集合等;

线程兼容

对象本身不是线程安全的,但是可以通过在调用端正确地使用同步手段来保证对象在并发环境中可以安全地使用。

线程对立

无论调用端是否采取同步措施,都无法再多线程环境中并发使用的代码。例:Thread类的suspend()resume()方法,两个线程同时持有一个线程对象,一个尝试中断一个尝试恢复,并发时无论是否进行同步,目标线程都存在死锁风险。常见还有System.setIn()System.setOut()System.runFinalizersOnExit()