缓存行失效的情况
1.如果X存储长度大于一个缓存行,加总线解决
2.cpu并不支持缓存一致性协议
线程分类:用户级线程 ULT,内核级线程 KLT
用户空间划分:用户空间,内核空间
用户和内核直接操作,是通过内核提供的交互接口进行
用户线程通过切换到内核态线程去调度cpu进行线程,只有Ring0级别才能调度cpu,内核态才有Ring0
Tss任务状态断:保存被挂起的线程上下文切换的数据
死锁:两个线程相互持有对方需要的锁对象 jstack 查看死锁
JMM的模型:是一种规范 跨平台
线程有工作内存,主内存有共享变量,围绕原子性,可见性,有序性展开
synchronized 关键字 出现线程上下文切换 也会触发去更新主内存的值
线程工作内存的副本,更新完后,会等待一定时间才刷回主内存
查看汇编指令:需要安装对应的插件
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -Xcomp
内存交互操作的原子比较与交换在底层的支持 cmp-chxg 汇编指令:
read load 成对 store write成对
volatile 保证了 有序性,可见性,但是原子性保证不了,因为for循坏conut值会丢失循坏次数
syn 锁 三个都保证了
有序性:
指令重排的话,前提遵守as-if-serial语义
synchronized锁升级: 无锁->偏向锁->轻量级锁->重量级锁 (不可逆)
32位mark word :
无锁时:对象的hashcode,对象分代年龄,是否偏向锁,锁标志位
线程进来先判断锁的状态,在mark word修改对应锁的状态,偏向锁是不会自动释放
T2去CAS竞争T1线程的时候,T1还没走完还不释放锁,偏向锁升级为轻量级锁
轻量级锁会复制对象头markword到当前线程栈空间上面,然后对象头markword前29位里面修改成LockRecord对象引用,LockRecord 的owner变量里面是引用指向对象头markword
T1还没走完,T2发起升级重量级锁,JVM会去调线程调度库pthread,从用户态到内核态,这是个比较耗时的操作,把warkword修改成重量级锁的指针,然后调用Pthread_mutex_lock进行线程阻塞挂起,阻塞后会把线程放到waitset等待队列里面去。
T1执行完cas修改warkword发现已经不是指向自己,已经是变成了重量级锁的指针,这时T1会去唤醒阻塞的线程。
AQS:抽象队列同步器 (双向指针的队列)
抽象出等待队列(公平),条件队列(非公平),独占获取,共享获取等待,依赖状态state记录锁的次数(重入,拿一次锁加1,释放时减1)
CLH变种队列(同步队列) 原生CLH队列让线程自旋,而AQS是阻塞
锁类型
是否锁同步资源 :悲观锁和乐观锁
是否阻塞:阻塞 不阻塞(自旋锁,自适应锁)
是否要排队:公平与非公平
一个线程多个线程能不能获取同一把锁:可重入锁与不可重入锁
多个线程能不能共享一把锁:共享锁与排它锁
把两个事情都要干完,两个都是拿得同一个锁,重复的拿到锁