《深入理解高并发编程》学习笔记【1】

最近在学习冰河老师的《深入理解高并发编程》
因此写点笔记来帮助日后回顾学习

幕后黑手

可见性

根因:缓存
表现:多线程处理同一变量,最终处理结果与预期不一致。

原子性

根因:线程切换
表现:多线程处理同一变量,最终处理结果与预期不一致。

有序性

根因:指令重排
表现:双重检查单例模式 new Instance() 指令重排导致线程B获取到线程A还未创建的对象

解决办法

按照需要禁用缓存和编译优化

java内存模型

Java内 存模型规范了Java虚拟机(JVM)如何提供按需禁用缓存和编译优化的方法

volatile

禁用CPU缓存

volatile int count = 0

Happens-Before原则

程序次序规则

同一线程里,修改变量对后续操作一定是可见的

volatile变量规则

volatile修饰的变量的写操作,先于 读操作

传递规则

A>B, B>C ==> A>B>C

锁定规则

synchronized

线程启动规则

A 启动 B,那么B能看到A在启动B前的各操作

线程终结规则

A中调用B.join() B执行完后 A继续执行,此时B的操作对A是可见的

线程中断规则

A中中断B ,B可以访问A的修改

对象终结原则

synchronized的原理

通过对象或者类上的monitor监视器锁来解决同步问题

修饰代码块 -> 锁定传入对象
修饰方法 -> 锁定当前实例对象this
修饰静态方法 -> 锁定是当前类对象

互斥锁解决原子性问题

ThreadLocal

线程A和线程B存储在ThreadLocal中的变量互不干扰,线程A存储的变量只能由线程A访问,线程B存 储的变量只能由线程B访问

根本原因在于,变量map其实是存在各自thread对象里,ThreadLocal仅仅是个白手套
InheritableThreadLocal 解决ThreadLocal 无法让子线程获取父线程ThreadLocal 变量的问题

并发问题的核心

分工

大任务分解成小任务交给合适的线程处理
Executor、Fork/Join和Future都是实现分工的一种方式。

同步

一个线程执行完任务后,如何通知其他的线程继续执行
CountDownLatch、 CyclicBarrier

互斥

同一时刻,只允许一个线程访问共享变量,强调的是线程执行任务的正确性。
synchronized、Lock、ThreadLocal、final

猜你喜欢

转载自blog.csdn.net/qq_34577234/article/details/125413902