多线程——线程安全及实现机制
文章目录
一、线程安全概念
讨论线程安全,需要以多个线程之间存在共享数据访问为前提。因为如果根本不存在多线程,又或者一段代码根本不会与其他线程共享数据,那么从线程安全的角度来看,程序是串行执行还是多线程并发执行对于它来说是没有什么区别的
线程不安全是指在一项工作进行期间,会被不断地中断和切换,对象的属性(数据)可能会在中断期间被修改和变脏,会造成程序运行错乱,甚至会造成重大经济损失,产生重大生产事故。所以我们程序员必须保证程序如何在高速地计算机中正确无误的运行
关于线程安全,《Java并发编程实战》作者做过一个比较恰当的定义:“当多个线程同时访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,调用方不需要进行任何其他的协调工作,调用这个对象的行为都能够获得正确的结果,那就称这个对象是线程安全的。”
上面这种定义要求线程安全的代码应该具备一个共同特征:代码本身封装了所有必要的正确性保障手段(如互斥同步等),令调用者无需关心多线程下的调用问题,更无需自己实现任何措施来保证多线程环境下的正确调用
二、Java 语言中的线程安全
上面我们已经有了线程安全的定义,那么在 Java 语言中,线程安全具体是如何实现的?有哪些操作是线程安全的?按照线程安全的 “安全程度” 由强至弱来排序,Java 语言中各种操作共享的数据分为以下几类:不可变、绝对线程安全、相对线程安全、线程兼容
1、不可变
在 Java 语言中,不可变对象一定是线程安全的,无论是方法实现还是方法的调用者,都不需要再进行任何线程安全的保障措施,只要一个不可变对象被正确的构建出来,那其外部的可见状态永远都不会改变,永远都不会看到它在多个线程之中处于不一致的状态。不可变带来的安全性是最直接、纯粹的
Java 语言中,如果多线程共享的数据是一个基本的数据类型,那么只要在定义的时候使用 final 关键字修饰它,就可以保证它是不可变的
2、绝对线程安全
绝对线程安全的定义是很严格的,一个类要达到 “不管运行时环境如何,调用者都不需要任何额外的同步措施”,可能付出的代价是非常高昂的,甚至无法实现
在 Java 语言中标注自己是线程安全的类,也并不是绝对的线程安全。比如 Vector 是一个线程安全的容器,大家应该不会