线程安全
来源:互联网 发布:mac os x10.7.5下载 编辑:程序博客网 时间:2024/04/28 12:12
因为线程共享相同的内存地址空间,且并发地运行,它们可能访问或修改其他线程正在使用的变量。这是十分方便的,因为它使得数据共享相对于其他的线程间通讯机制都更加简单。但是这其中也存在着巨大的风险:当数据意外改变时,线程可能会出现混乱。允许多线程访问和修改相同的变量,给顺序编程模型引入了一些非顺序因素,这可能会造成混乱,并且难以发现错误的原因。为了使多线程程序的行为可预见,访问共享的变量必须经过合理的协调,这样线程才不会互相干扰。
非线程安全的序列生成器
public class UnsafeSequence { private int value; public int getNext() { return value++; }}
线程安全的序列生成器
public class Sequence { private int value; public synchronized int getNext() { return value++; }}
编写线程安全的代码,本质上就是管理对状态(state)的访问,而且通常都是共享的,可变的状态
通俗地说,一个对象的状态就是它的数据,存储在状态变量中。
所谓共享,是指一个变量可以被多个线程访问;所谓可变,是指变量的值在其生命周期内可以改变。线程安全好像是关于代码的,但真正要做的是在不可控制的并发访问中保护数据。
一个对象是否应该是线程安全的取决于它是否被多个线程访问。线程安全的这个性质取决与程序中如何使用对象,而不是对象完成了什么。保证对象的线程安全性需要使用同步来协调对其可变状态的访问;若是做不到这一点,就会导致脏数据和其他不可预测的后果。
无论何时,只要有多于一个的线程访问给定的状态变量,而且其中某个线程会写入该变量,此时必须使用同步来协调线程对该变量的访问。
线程安全的定义
当多个线程访问一个类时,如果不用考虑这些线程在运行时环境下的调度和交替执行,并且不需要额外的同步及在调用方代码不必做其他的协调,这个类的行为仍然是正确的,那么这个类就是线程安全的。
线程安全的类封装了任何必要的同步,因此客户不需要自己提供。
无状态对象永远是线程安全的。
为了确保线程安全,“检查再运行”操作(如惰性初始化)和读-改-写操作(如自增)必须是原子操作。
为了保护状态的一致性,要在单一的原子操作中更新相互关联的状态变量。
不可变性
创建后状态不能被修改的对象叫做不可变对象。不可变对象天生就是线程安全的。它们的常量(域)是在构造函数中创建的。
不可变状态永远是线程安全的
无论是Java语言规范还是Java存储模型,都没有关于不可变性的正式定义,但是不可变性并不简单地等于将对象中的所有域都声明为final类型,所有域都是final类型的对象仍然可以是可变的,因为final域可以获得一个可变对象的引用。
只有满足如下状态,一个对象才是不可变的- 它的状态不能在创建后再被修改- 所有域都是final类型,并且- 它被正确创建正如“将所有的域声明为私有的,除非它们需要更高的可见性”一样,“将所有的域声明为final类型,除非它们是可变的”,也是一条良好的实践。
参考文献
戈茨. JAVA并发编程实践[M]. 电子工业出版社, 2007.
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- 线程安全
- Xcode 8 证书管理 Signing for "xxxx" requires a development team
- Spring4.3.x 浅析xml配置的解析过程(3)——使用DocumentLoader创建Document对象
- 1057. Stack (30)
- 斜率优化
- Android Studio 关于用户ID信息的保存
- 线程安全
- 设计模式之适配器模式
- Python闭包编程
- |Hdu 2087|KMP|剪花布条
- String StringBuilder StringBuffer
- 我入门的几本书
- 百度大脑和图灵机器人制作一个简单的自动聊天机器人【PHP代码】
- java之自己做一个ThreadLocal
- 如何简单的实现一个富文本,图文混排编辑器