当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么这个类就是线程安全的。
也可以理解为:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
线程安全也是有几个级别的:
1)不可变
像String、Integer、Long这些,都是final类型的类,任何一个线程都改变不了它们的值,要改变除非新创建一个,因此这些不可变对象不需要任何同步手段就可以直接在多线程环境下使用
2)绝对线程安全
不管运行时环境如何,调用者都不需要额外的同步措施。要做到这一点通常需要付出许多额外的代价,Java中标注自己是线程安全的类,实际上绝大多数都不是线程安全的,不过绝对线程安全的类,Java中也有,比方说CopyOnWriteArrayList、CopyOnWriteArraySet
3)相对线程安全
在一般情况下,调用者都不需要考虑线程同步,大多数情况下,都能够正常运行。相对线程安全也就是我们通常意义上所说的线程安全,像Vector这种,add、remove方法都是原子操作,不会被打断,但也仅限于此,如果有个线程在遍历某个Vector、有个线程同时在add这个Vector,99%的情况下都会出现ConcurrentModificationException,也就是fail-fast机制。
4)线程非安全
在多线程环境下,调用者需要考虑同步问题。如果调用者通过额外的同步机制,可以保证线程的安全性。
jdk中,ArrayList、hashMap等对象都是非线程安全的。所以在使用这些对象的时候,都要考虑是否会发生线程安全问题。
5)线程对立
在多线程环境中,无论采用什么样的机制,都无法解决线程安全问题。这种还是极为少见的。比如java.lang.Thread类,提供了suspend,stop,resume方法。
suspend 和 resume 方法可能导致两个线程死锁。