1 数据竞跑:
多个线程同时对某个共享变量进行操作,且这些操作中至少有一个是写操作时造成的程序错误。
2 死锁 vs 活锁
多个线程依赖多个锁时,出现死锁的原因是:每个线程加锁操作的执行顺序不一致
活锁是指,多个线程同时trylock一个锁,都不成功,则都无法进入临界区操作,只能一次次尝试。导致不必要的性能开销。
3 锁竞争的常用解决办法:
- 1 避免使用锁:调整逻辑顺序,避免对资源的争用; 资源复制,使得每个线程都有一份资源,适当时机再进行资源的同步
- 2 使用读写锁减少竞争:适用于读多写少场景
- 3 保护数据而不是操作:并行的效率关键取决于程序中串行的部分,所以尽量减少同步块内操作
- 4 尽量使用轻量级原子操作
- 5 粗粒度/细粒度锁
- 6 无锁编程:java.util.concurrent
4 并行编程固有难题:
- 负载均衡
- 顺序依赖
- 同步
5 当前同步机制:
- volatile 变量:轻量级多线程同步机制,不会引起上下文切换和线程调度。仅提供内存可见性保证,不提供原子性。
- CAS 原子指令:轻量级多线程同步机制,不会引起上下文切换和线程调度。它同时提供内存可见性和原子化更新保证。
- CAS:Intel,AMD 和 SPARC 的多处理器系统支持“比较并交换”(compare-and-swap,CAS)指令
- LL/SC:IBM PowerPC,Alpha AXP,MISP 和 ARM 的多处理器系统支持“加载链接 / 存储条件”(load-linked/store-conditional,LL/SC)指令
- 内部锁和显式锁:重量级多线程同步机制,可能会引起上下文切换和线程调度,它同时提供内存可见性和原子性。
6 非阻塞算法:
一个线程的失败/挂起不会引起其它线程的失败/挂起