synchronized&volatile
用户态与内核态
早期的synchronized是重量级锁,申请锁通过kernel来申请,系统调用,用户空间-》内核空间,代价太大
CAS:自旋锁
怎么解决CAS的ABA问题?加version、布尔值、时间戳都可以
Automic类用的是CAS,底层通过指令cmpxchg来实现,但是这个指令不是原子性的,需要指令lock_if_mp来保证原子性(如果mp就lock)mp:multi processor 多处理器 lock:锁定总线(cpu去内存访问值的时候锁定总线)
JOL:java object layout
升级过程:图 主线
偏向锁:将线程ID放到对象的markword里,并不调用操作系统
自旋锁:线程修改markword的ID,谁修改成功,谁持有
重量级锁:太多线程自旋,竞争激烈,消耗资源太多,直接使用重量级锁,所有自旋的线程进waitSet等待队列,不再自旋
什么时候升级成重量级锁:1.6之前线程自旋10次或自旋线程超过cpu总核1/2,之后:自适应自旋,根据每个线程的情况决定升不升重量级锁,我理解是比较自旋还是切换内核态占用资源多
关于java -xx:多是涉及jvm调优的
为什么BiasedBlocking偏向锁延迟时间是4秒钟,jvm启动完之后隔4s再来开启偏向锁,如果这个时间之内有竞争锁,就不启用偏向锁了,直接启用轻量级锁,效率反而更高
锁重入,一个方法调用另一个方法,两个方法中都有对某个对象的加锁
重量级锁底层实现:ObjectMonitor,AQS
volatile:
线程间可见;java工作模型,线程(cpu)从内存中读取数据到自己的缓存,不加volatile的话不会去读主存数据;通过缓存一致性协议实现。cpu每次会读64个字节,所以可能会产生读的一块数据内有两个数据都有volatile,效率慢,解决方法:缓存行对其
禁止指令重排:指令重排乱序
对象创建过程
DCL:double check lock dcl必须加volatile,可能会造成拿到半初始化的数据,在百万并发的情况下,有百万分之一的情况概率
volatile的底层是内存屏障,在jvm和cpu级别是完全不一样的概念