那些年读过的书《Java并发编程实战》一、构建线程安全类和并发应用程序的基础
1、线程安全的本质和线程安全的定义
(1)线程安全的本质
并发环境中,当多个线程同时操作对象状态时,如果没有统一的状态访问同步或者协同机制,不同的线程调度方式和不同的线程执行次序就会产生不同的不正确的结果。要确保获得最后正确的结果就需要对线程访问对象状态
的操作上进行同步或者协同,使多个线程无论在什么样的调度方式和线程执行顺序的情况中,都能产生正确的结果。
线程安全的本质就对(对象)状态的访问操作进行统一管理,使之在不同的执行环境下均能产生正确的结果。也就是在不同的并发环境下,保持对象状态的不变性,保证对象的不变性在不同的线程执行环境下不被破坏。
对象状态的类型:可变的、不可变的、共享的、封闭的。不同类型的状态访问操作在多线程的访问操作上呈现不同的特征。
对象状态的类型
多线程访问
可变的 可以修改对象状态的值,肯能造成数据失效,线程不安全 共享的 可以修改对象状态的值,肯能造成数据失效,线程不安全 不可变的 不可修改对象状态的值,线程安全 封闭的 封闭在单个线程内,不在多个线程间共享,线程安全
(2)线程安全的定义
线程安全性定义:
当多个线程访问某个类时,不管运行环境采用何种调度方式或者线程间如何交替执行,并且在主调代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。
线程安全的两个特性:原子性操作和状态可见性
原子性操作:状态的访问操作呈现原子性操作不可分割
状态可见性:状态在多个线程内可见
2、多线程并发中遇到的问题
(1)竞态条件:线程间不恰当的执行时序而导致出现不正确结果的情况。
某个计算结果的正确性取决于多个线程的交替执行时序时,就会产生竞态条件。
(2)复合操作:复合操作间不是原子性操作,是可以拆分的操作,易改变原有的操作时序,从而导致出现竞态条件。
(3)失效数据:状态访问操作上缺乏同步导致数据在某些线程内出现失效。
3、如何通过同步来避免多个线程同时访问相同的数据?(加锁机制)
(1)加锁机制
加锁机制是Java中确保原子性操作的内置机制,保证了多个原子性操作组合、复合操作呈现原子性操作以防止出现竞态条件。
同步块代码:Java内置的锁机制保证了操作的原子性。实例方法同步块的锁就是方法调用所在的实例对象,静态的同步块方法的锁就是Class对象。
Java内置锁:每个Java实例都可以用作一个实现同步的锁,这些锁称为内置锁或者监视锁,Java内置锁是一种互斥锁,最多只能有一个线程持有该锁。
(2)用锁来保护状态
(3)活跃性与性能
4、如何共享和发布对象,使之能够安全的被多个线程同时访问?
(1)如何实现可见性
(2)如何确保对象不被发布
(3)如何安全发布对象