《并发编程实战》笔记
1. 并发编程的优势
- 发挥多处理器的能力
- 建模简单
- 异步处理任务
2. 活跃性问题和性能问题
- 上下文的切换问题
2.1 重排序
重排序:当A线程修改变量,而B线程读取变量的时候,根据处理器的切换,可以出现非常复杂到可能性
3. 线程安全
3.1 同步带来的问题修复办法
- 不再线程之前共享该变量状态
- 状态变量不可变
- 访问状态的时候同步
3.2 线程安全性
线程的正确性
- 某个类到行为和规范完全一致
- 所见即所知
当多个线程访问某个类,不管运行环境使用什么方式调用或者线程将交替运行,主调代码不需要任何额外的同步或者协同,都能表现正确行为
线程安全类封装了必要到同步机制,客户端是无法进行进一步措施的
无状态对象一定是想线程安全的
3.3 锁的类型
3.3.1 内置锁(互斥锁)
就是被synchronize
关键字修饰到方法
特性:当用户持有内置锁的时候,只有一个线程可以持有此锁,例如:如果A持有了锁,B访问,B就会阻塞
- 静态的
synchronize
方法以Class作为锁 - java内置锁的基本代为是对象
优点:
- 可以是方法具有原子性
- 多个线程访问不会发生竞态条件
缺点:
- 导致代码完全同步
- 严重消耗性能
3.3.2 可重入锁
特性:如果一个线程持有由他自己持有的锁,将重入,意味着锁到细粒度为“线程”,不是“调用”,
如果内置锁不是可重入的,那么将会发生死锁
3.4 用锁来保护状态
错误认知:
操作共享到变量的时候才需要同步
正确方式:
只有多个线程同时访问的可变数据才需要通过锁保护
可能被多个线程访问的可变状态常量,在访问他的时候,需要持有同一个锁,这个变量是锁保护的
当一个方法执行时间较长,并且不会影响状态改变的时候,一定不能够使用锁
3.5 内存可见性
除开原子性之外,锁的另一个重要作用是实现内存上可见
3.5.1 什么是内存可见性:
内存可见性是指一个共享变量在A线程可以看到线程B的到操作,防止A读取到失效数据
3.5.2 Volatie 变量
什么时候使用Volatie变量
- 对变量的写入操作不依赖变量得值,或者确保某个单线程会修改变量才使用
- 此变量不会和其他状态变量一起纳入不变性条件
- 访问变量的时候不需要加锁
3.6 发布和逸出
发布:指一个对象发布到另一个对象的作用域里面,脱离当前作用域
逸出:被发布的对象同时发布了其他对象的信息,这时候就是逸出
4. 线程封闭
4.1 Ad-hoc 线程封闭
含义:线程封闭(Thread Confinement):仅在单线程内访问数据,不需要同步。
4.2 栈封闭
含义: 在栈封闭中,只能通过局部变量才能访问对象。
栈封闭(也被称为线程内部使用或者线程局部使用)比Ad-hoc线程封闭更易于维护,也更加健壮。
4.3 ThreadLocal类
这个类能使线程中的某个值与保存值的对象关联起来。ThreadLocal提供了get与set等访问接口或方法,这些方法为每个使用该变量的线程都存有一份独立的副本,因此get总是返回由当前执行线程在调用set时设置的最新值。
5. 不变性
什么是不可变对象?
- 创建之后不允许改变
- 对象的所有域都是final
- 对象是正确创建的(this没有逸出)
Final
- 如果不需要域是不可变的,则需要尽量为private
- 如果对象不需要改变,尽量为private 域