相关面试题:
计算机组成
a=2+3 2,3从内存拿到cpu -> 计算->结果放到内存
操作系统管理线程的调度,os把app的线程指令扔到cpu
调度策略,最常见的cfs
线程数不一定越多越好,线程切换
CAS compare and swap
在JDK中的应用,原子类 do{}while(!cas)
ABA问题解决
增加一个版本号,读取和版本号,修改版本号,比较版本号,也可以用boolean值来标记是否改过。
CAS底层实现
unsafe类中的本地方法,compareandswap
java内存布局
对象头:markword 、 calss pointer 、 数组长度
实例数据:
对齐填充
可以用以下工具查看
指针压缩
+UseCompressedClassPointer 头部指针压缩
+UseCompressedOops 普通指针压缩 比如对象属性里面的指针
Object o = new Obeject();占几个字节?
默认开启了指针压缩:
markword - 8 klasspointer - 4 对齐填充 - 4 --------------------- 16字节
没有开启指针压缩:
markword - 8 klasspointer - 8 --------------------------------------- 16字节
boolean byte 1
char short 2
int float 4
long double 8
string 4普通指针压缩 未开启 8
synchronized
synchronize相关信息都记录在markword里面
偏向锁默认打开
锁升级过程
前面3种都属于无锁状态
偏向锁,同一个线程
轻量级锁/自旋锁,来了第二个线程,CAS操作
自旋次数过多(10)||线程超过cpu1/2 会消耗太多cpu 因此 会进行锁升级成为重量级锁
lockrecord里面记录的hashcode
重量级锁才是真的有锁mutex,向内核态申请,
重量级锁有个队列(无序,非公平锁),在队列里处于wait状态,不消耗CPU
偏向锁有时延,可以通过参数改成0,默认4s
1.6以后自适应
锁降级只有在GC时才可以降级,除了GC线程没有其他线程访问,没有意义,可以认为锁降级不存在。
锁粗化,可以把锁加在whil外面
synchronized的最底层实现
也是 lock cmpxchg,volatile底层实现也是
缓存行
读数据从外往里读是按照块读,块——cache line/缓存行,一次性也就是一行数据 = 8字节
从内存往cpu读数据,一块一块读,一次读64位,因为总线宽64bits
缓存行大都数是64字节 bytes
cache line size = 8 字节 cache size = 64字节
cpu层级的数据一致性是以缓存行为单位的
缓存行对齐优化
CPU 缓存一致性协议 MESI(intel使用,其他的cpu可能用别的协议)
volatile
volatile解决了两个问题:
可见性,
顺序性(禁止指令重排序)
指令重排序
指令重排的实验,正常情况 xy可能为01,10,11,但是不会出现00,乱序执行结果出现了00
如何阻止乱序执行?
jvm层面
cpu层面
线程1执行了指令7 线程2执行第一次判断!=null直接返回版初始化的实例
指令重排序:单线程最终一致性就可以指令重排序。不考虑多线程情况。所以才需要加volatile。
OS通过加内存屏障
java通过加关键字volatile,JVM看到指令后加屏障(4种,规范),c++通过lock实现,只允许一条指令穿过总线
jvm四种引用
强:内存不够也不回收 OOM
软若虚实际上有两个引用 SoftReference<byte> b = new SoftReference<new byte[1024*1024*10 ]> b--new Soft...是强引用 new Soft...--new byte....才是软引用,其他两个同理
软:缓存 eg.图片,内存不够的时候回收掉
*弱:发生垃圾回收时直接回收。一次性。 Threadlocal,在spring事务有用到
threadlcoal用完后,key为null,value需要remove,否则还是会内存泄漏
虚:虚引用get不到,跟没有一样,用处:管理对外内存。NIO 零拷贝,直接操作os缓冲区数据。GC垃圾回收不会回收对外内存,垃圾线程监听对jvm里面的内存,被回收了就加紧queue,queue里面对应的堆外内存就会做相应处理。
JVM禁止指令重排序的情况
happens-before规则
volatile实现
哈哈哈哈
标签:缓存,字节,编程,并发,指令,线程,内存,相关,cpu From: https://www.cnblogs.com/jyzyz/p/18211268