最近在学习并发相关的知识,为了更好的理解并发相关的知识,我做了以下笔记。笔记持续更新中,希望对大家有所帮助,有不对的地方也请大家帮忙指正,一起共同学习和成长!
当前知识结构适合人群:准备学习并发相关的知识,但无从着手的朋友,高手请忽略。
并发及并发知识结构
- 并发的基础:
- cpu多级缓存
- 由于计算机的存储设备与处理器的运算能力之间有几个数量级的差距,所以现代计算机系统都不得不加入一层读写速度尽可能接近处理器运算速度的高速缓存(cache)来作为内存与处理器之间的缓冲:将运算需要使用到的数据复制到缓存中,让运算能快速进行,当运算结束后再从缓存同步回内存之中没这样处理器就无需等待缓慢的内存读写了
- 现在很多都拥有3级缓存,离处理器越近的缓存访问越快。
- 高速缓存引起的问题:
- 缓存的一致性(每个处理器都有自己的高速缓存,而他们又共享同一主存,如下图所示:多个处理器运算任务都涉及同一块主存,需要一种协议可以保障数据的一致性,这类协议有MSI、MESI、MOSI及Dragon Protocol等。Java虚拟机内存模型中定义的内存访问操作与硬件的缓存访问操作是具有可比性的)
- 代码进行乱序执行优化(为了使得处理器内部的运算单元能竟可能被充分利用,处理器可能会对输入代码进行乱起执行(Out-Of-Order Execution)优化,处理器会在计算之后将对乱序执行的代码进行结果重组,保证结果准确性。编译器和内存系统也会进行指令乱序的执行优化)
- java内存模型(Java Memory Model,JMM)
- 主要了解工作内存与主内存之间的八种操作
- lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。
- unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
- read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用
- load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
- use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。
- assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
- store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作。
- write(写入):作用于主内存的变量,它把store操作从工作内存中一个变量的值传送到主内存的变量中。
- 如果要把一个变量从主内存中复制到工作内存,就需要按顺寻地执行read和load操作,如果把变量从工作内存中同步回主内存中,就要按顺序地执行store和write操作。Java内存模型只要求上述操作必须按顺序执行,而没有保证必须是连续执行。也就是read和load之间,store和write之间是可以插入其他指令的,如对主内存中的变量a、b进行访问时,可能的顺序是read a,read b,load b, load a。Java内存模型还规定了在执行上述八种基本操作时,必须满足如下规则:
- 不允许read和load、store和write操作之一单独出现
- 不允许一个线程丢弃它的最近assign的操作,即变量在工作内存中改变了之后必须同步到主内存中。
- 不允许一个线程无原因地(没有发生过任何assign操作)把数据从工作内存同步回主内存中。
- 一个新的变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量。即就是对一个变量实施use和store操作之前,必须先执行过了assign和load操作。
- 一个变量在同一时刻只允许一条线程对其进行lock操作,lock和unlock必须成对出现
- 如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行load或assign操作初始化变量的值
- 如果一个变量事先没有被lock操作锁定,则不允许对它执行unlock操作;也不允许去unlock一个被其他线程锁定的变量。
- 对一个变量执行unlock操作之前,必须先把此变量同步到主内存中(执行store和write操作)。
- 主要了解工作内存与主内存之间的八种操作
- cpu多级缓存
- 线程安全性
- 原子性 提供了互斥访问,同一时刻只有有一个线程对它进行操作
- 可见性 一个线程对主内存的修改能够被及时其它线程观察到
- 有序性 在一个线程中观察其它线程的指令执行顺序,由于指令重排序的存在,该观察是杂乱无序的
- Atomic包
- AtomicInterger、AtomicIntergerArray
- AtomicBoolean
- AtomicLong、AtomicLongArray
- LongAddr
- AtomicDouble、AtomicDoubleArray
- DoubleAddr
- AtomicReference
- AtomicReferenceFieldUpdater
- AtomicStamedReference 解决ABA问题
- synchronized与lock
- volatile
- CAS算法
- happens-before原则
- 安全发布对象
- 不可变方法
- 不可变变量
- final关键字
- this逃逸
- 安全发布对象
- 不安全发布对象的举例
- 单例的各种实现
- 线程封闭、并发容器、同步容器
- 堆栈封闭
- jdbc线程封闭
- ThreadLocl
- 并发容器
- 同步容器
- AQS等J.U.C组件
- CountDownLatch
- Semaphore
- CyclicBarrier
- Condition
- FeatureTask
- Fork/Jion框架
- BlockingQueue
- 线程调度
- new Thread弊端
- Executors 四种线程池的创建方式及场景
- ThreadPoolExecutor
- 线程扩展及补充
- 死锁
- Spring 与多线程
- Map 线程不安全与安全
- ReentrantLock 与锁