线程同步
3.1线程同步机制简介
线程同步机制是一套用于协调线程之间的数据访问机制,该机制可以保障线程安全;
Java平台提供的线程安全机制包括:锁,volatile, final, static, 以及相关的API,如 Object.wait()/Object.notify()等
MESI缓存一致性协议简介
flush处理器缓存,
3.2 锁概述
线程安全问题产生的前提是多线程并发访问共享数据。一个程序的代码是走走停停的
锁保障线程安全:将多线程并发访问转换为串行访问,即一个共享数据一次只能被一个线程访问
锁具有排他性,一个互斥锁一次只能被一个线程持有
JVM将锁分为内部锁,和显示锁两种,内部锁通过synchronized关键字实现
;显示锁通过java.concurren.locks.lock接口的实现类
3.2.1锁的作用
通过互斥保障原子性。一个锁一次只能被一个线程持有,这就保证临界区的代码一次只能被一个线程执行,代码所执行的操作自然就具有了不可分割的特性,即具备了原子性
锁的获得隐含这刷新处理器缓存的动作(将主内存的数据更新到工作内存(从内存读到缓存))
释放锁是冲刷处理器缓存(将工作内存的数据更新到主内存(从缓存写到内存))
锁能够保障有序性,写线程在临界区锁执行的在读线程所执行的临界区看来像是完全按照源码顺序来执行额
3.2.2锁相关的概念
可重入性 一个线程持有该锁的时候能再次(多次)申请该锁
synchronized 属于非公平锁 显示Lock锁既支持公平锁又支持非公平锁
一个锁可以保护的共享数据的数量大小称为锁的粒度
- 过大 导致申请锁时进行不必要的等待
- 过细 会增加锁调度的开销
3.3 内部锁:synchronized关键字
Java 中的每个对象都有一个与之关联的内部锁,也被称为监视器(Monitor)是拍她锁
修饰代码块
修饰实例方法
修饰静态方法
脏读:读到了中间值而不是修改后的值
原因:对共享数据的修改与对共享数据的读取不同步
解决:不仅对修改数据的代码进行同步还要对读取数据的代码块同步
同步过程中线程出现异常,会自动释放锁对象
死锁:在多线程同步时可能会需要使用多个锁,如果获得锁的顺序不一致可能会导致死锁
当需要获得多个锁,所有线程获得锁的顺序保持一致即可
3.4 轻量级同步机制:volatile关键字
volatile的作用
强制线程从公共内存中读取变量的值而不是从工作内存读取
使变量在多个线程可见
3.5 CAS
是由硬件实现的
将read-modify-write这类的操作转为原子操作