- 两种同步机制:
- 控制同步:例如,当一个任务的开始依赖于另一个任务的结束时,第二个任务不能再第一个任
务 完成之前开始。 - 数据访问同步:当两个或更多任务访问共享变量时,再任意时间里,只有一个任务可以访问该
变量。
- 控制同步:例如,当一个任务的开始依赖于另一个任务的结束时,第二个任务不能再第一个任
- 原子操作和原子变量
- 原子操作 :是一种发生在瞬间的操作。在并发应用程序中,可以通过一个临界段来实现原子操作,以便对整个操作采用同步机制。
- 原子变量 :是一种通过原子操作来设置和获取其值的变量。可以使用某种同步机制来实现一个原子变量,或者也可以使用CAS以无锁方式来实现一个原子变量,而这种方式并不需要任何同步机制。
- 线程之间通信方式
- 共享内存 :通常用于在同一台计算机上运行多任务的情况。任务在读取和写入值的时候使用相同的内存区域。为了避免出现问题,对该共享内存的访问必须在一个由同步机制保护的临界段内完成。
- 消息传递 :通常用于在不同计算机上运行多任务的情形。当一个任务需要与另一个任务通信时,它会发送一个遵循预定义协议的消息。如果发送方保持阻塞并等待响应,那么该通信就是同步的;如果发送方在发送消息后继续执行自己的流程,那么该通信就是异步的。
- 死锁的四个条件
- 互斥:资源不可共享
- 占有并等待条件:一个任务既占有了资源,同时还要去请求别的资源
- 不可剥夺:资源只能被那些持有它们的任务释放。
- 循环等待:相互循环焦灼
- 如何避免死锁
- 忽略,遇到问题就重启
- 检测机制,如果发现就强制释放某一个资源(数据库的事务关闭)
- 预防:打断那四个条件
- 规避:执行前先判断是否所有资源可以获取
活锁
如果系统中有两个任务,它们总是因对方的行为而改变自己的状态, 那么就出现了活锁。最终结果
是它们陷入了状态变更的循环而无法继续向下执行 翻译就是:两人走路互相让路,同时左,同时右JMM:Java内存模型
操作系统:

- 操作系统:因为存在CPU缓存一致性协议,例如MESI,多个CPU核心之间缓存不会出现不同步的问题,不会有“内存可见性”问题。
- 重排序
- 编译器重排序 :对于没有先后依赖关系的语句,编译器可以重新调整语句的执行顺序。
- CPU指令重排序 :在指令级别,让没有依赖关系的多条指令并行。
- CPU内存重排序 :CPU有自己的缓存,指令的执行顺序和写入主内存的顺序不完全一致。(“内存可见性”问题的主因 )
- 内存屏障
- 禁止编译器重排序和 CPU 重排序
- 会用volatile就可以了,此外还有Unsafe里面的函数
- as-if-serial
- 不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。
volatile
- 单例模式的DCL(Double Checking Locking)
public class Singleton {private static volatile Object instance; // 需要保证操作不重排序public static Singleton getInstance() {if (instance == null) {synchronized(Singleton.class) {if (instance == null) {// 此处代码有问题instance = new Singleton();}}}return instance;}}
- 单例模式的DCL(Double Checking Locking)
happen-before的总结
1.单线程中的每个操作,happen-before于该线程中任意后续操作。
- 对volatile变量的写,happen-before于后续对这个变量的读。
- 对synchronized的解锁,happen-before于后续对这个锁的加锁。
- 对final变量的写,happen-before于final域对象的读,happen-before于后续对final变量的读。
