# ConcurrentDemo **Repository Path**: wangddt/ConcurrentDemo ## Basic Information - **Project Name**: ConcurrentDemo - **Description**: 1111111111111111111 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-08-30 - **Last Updated**: 2026-03-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ConcurrentDemo #### 介绍 1. 本项目属于个人关于并发的练习,相关对照视频地址[https://www.bilibili.com/video/av65160243](https://www.bilibili.com/video/av65160243)的视频 2. 鉴于是个人练习,故对视频所示源码有部分调整(如由日志输出改为直接打印等细微差距,不影响核心代码) 3. 目录结构参考分p内容 #### 线程安全的体现 1. 原子性 2. 可见性 3. 有序性 ##### synchronized 1. 修饰代码块:大括号括起来的代码,作用于调用的对象 2. 修饰方法:整个方法,作用于调用的对象 3. 修饰静态方法:整个静态方法,作用于所有对象 4. 修饰类:括号括起来的部分,作用于所有对象 ##### 原子性-对比 1. synchronized:不可中断锁,适合竞争不激烈,可读性好 2. Lock:可中断锁,多样化同步,竞争激烈时能维持常态 3. Atomic:竞争激烈时能维持常态,比lock性能好,只同步一个值 #### 可见性 ##### 线程间不可见原因 1. 线程交叉执行 2. 重排序结合线程交叉执行 3. 共享变量更新后的值没有在工作内存与主内存间及时更新 ###### 可见性-synchronized 1. 线程解锁前必须将共享变量的最新值刷新到主内存 2. 线程加锁时,将清空工作内存中共享变量的值,使用共享变量时共享变量时需要从主内存中重新获取最新值(注:加锁和解锁是同一把锁) ###### 可见性-volatile(volatile不具备原子性) 1. 通过加入内存屏障和禁止重排序优化来实现 2. 对volatile变量写操作时,会在写操作后加入一条store屏障指令,将本地内存中的共享变量值刷新到主内存 3. 对volatile变量读操作时,会在读操作前加入一条load屏障指令,从主内存中读取共享变量 ####### volatile的使用应同时具备以下条件(适用于标识状态量) 1. 对变量的写操作不依赖当前值 2. 该变量没有包含在具有其他变量的不变式中 ##### 有序性 1. java内存模型中允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性 2. volatile、synchronized、lock ######有序性-happens-before原则(编译重排序,参考编译原理) 1. 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作 2. 锁定规则:一个unlock操作先行发生于后面对同一个锁的lock操作 3. volatile变量规则:对一个变量的写操作先行发生于后面对该变量的读操作 4. 传递规则:如果操作A先于操作B发生,而操作B又先于操作C发生,则可得出操作A先于操作C发生 5. 线程启动规则:Thread对象的start()方法先于此线程的每一个动作 6. 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断时间的发生 7. 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行 8. 对象的终结规则:一个对象的初始化完成先于他的finalize()方法的开始 ######线程安全性-总结 1. 原子性:Atomic包、CAS算法、synchronized、Lock 2. 可见性:synchronized、volatile 3. 有序性:happens-before(当两个操作无法从该原则中推导出来,则可能出现乱序的情况) #####发布对象 1. 发布对象:使一个对象能够被当前范围之外的代码所使用的 2. 对象逸出:一种错误的发布,当一个对象还未构造完成时,就使其被其他线程所见 ######安全发布对象 1. 在静态初始化函数中初始化一个对象的引用 2. 将对象的引用保存到volatile类型域或AtomicReference对象中 3. 将对象的引用保存到某个正确构造对象的final类型域中 4. 将对象的引用保存到一个由锁保存的域中 #####不可变对象 1. 对象创建后其状态不能改变 2. 对象所有域都是final类型 3. 对象是正确创建的(在对象创建期间,this没有逸出) 4. 注:所谓发布对象是指使一个对象能够被当前范围之外的代码所使用。所谓逸出是指一种错误的发布情况,当一个对象还没有构造完成时,就使它被其他线程所见,这种情况就称为对象逸出。 #####线程封闭 1.Ad-hoc 线程封闭:程序控制实现,最糟糕,忽略 2.堆栈封闭:局部变量,无并发问题 3.ThreadLocal(利用map实现)线程封闭:特别好的封闭方法 #####线程安全-同步容器 1. ArrayList ->Vector(impl List),Stack(extends Vector); 2. HashMap->HashTable(k,v 不能为null) 3.Collections.synchronizedxxx(List、Set、Map)