编写线程安全的代码,实质上是管理对共享,可变的状态(即储存在变量中的数据)的访问
保证对象的线程安全性需要使用同步来协调对可变状态的访问,否则会导致脏数据的产生或者其他后果
java中首要的同步机制是sychronized关键字,它提供了独占锁,初次之外还有bolatile变量,显示锁,原子变量
面向对象技术—封装为设计线程安全的类提供了巨大的帮助(主要由于数据的隐藏和私有化)
线程安全:指当多个线程访问一个类时,如果并不用考虑这些线程在运行时环境下的调度和交替执行,也不需要额外的同步和协调,该类的行为仍然是正确的。
无状态对象永远是线程安全的(无状态指不包含任何域也不引用任何类的域)
原子操作,即不可分割的作用(++a不是院子操作,因为实质上是读改写三个步骤)
当计算的正确性依赖于运行时相关的时序或者线程之间的调度时会产生竞争条件(最常见的竞争条件,检查再运行,存在一个潜在的过期值作为下一步操作的依据)
简单的例子,你发现文件X不存在(潜在过期值),于是乎你去创建了一个文件X。在你发现和创建的时间内,另一个人已经创建了文件X
检查再运行最常见用法是惰性初始化,其目的是延迟对象的初始化,直到程序真正使用它,同时确保它只初始化一次
ps:竞争条件不等同于数据竞争,数据竞争发生于没有使用同步协调所有非final公共域,如一个线程刚写入一个值,被另一个线程读取的情况
java.lang.concurrent.atmoic包中包含原子变量类(都属于线程安全类),这些类用来实现数字和对象引用的原子状态转化
为了保护状态的一致性,要在原子操作中更新相关的状态变量
java提供了强制原子性的内置锁机制,synchronized块,synchronized分为两部分,一个是锁对象的引用,一个是锁保护的代码块。至于synchronized方法上的锁就是方法所在的对象本身,而静态方法的锁就是从对应的class中获得
每个java对象都可以成为一个锁,这种内置的锁成为内置锁或者监视器锁。执行线程在进入synchronized代码块之前会自动获得锁,而无论是正常运行结束还是抛出异常,当线程放弃执行synchronized块时,会自动释放锁
内置锁同时也扮演着互斥锁的角色
重进入????????