部分真题
计算机组成原理
进程和线程的本质区别?
进程: 操作系统分配资源的基本单位
线程:CPU调度(操作系统执行)的基本单位
线程切换:线程调度,需要资源占用,所以线程不宜过多
jvm级别的线程
虚拟机的线程和操作系统线程的对应关系?
- hotspot jvm线程 和 内核线程 一一对应
- synchronized(0),需要等待线程执行完毕,jdk1.2之前,由OS帮忙管理线程 -- 重量级锁
- 无锁 - 偏向锁 - 自旋锁 - 重量级锁(必须让操作系统协助管理,即为重量级)
虚拟机管理线程方式
- 虚拟出寄存器,虚拟的PC(记录线程切换时执行位置)
- 管理属于用户控件的线程
- 轻量级的线程 - 纤程(用户级别线程。go天然支持高并发,意指天然支持纤程/协程
go routine
go关键词开启一个go routine,对应java的runnable,每次go XXX相当于起一个个任务,扔到一个个队列中,让系统线程去执行,协程,线程比例 为 M:N
为什么用户级别线程提高了效率?
省去了操作系统管理线程的步骤,省去了线程的上下文切换,把切换部分放到了jvm
- CAS:compare and swap | compare and set
操作后回写时先查看是否依然为原本值,依然保持则回写;值已经变动则重新取值操作后再回写(自旋锁
,乐观锁
) - 如何处理CAS的ABA问题:
拿出值处理回写时,发现值依然为零,但无法确定这个值是否是被处理过但是又回到了原始值
。如何处理?加版本! - 自旋锁一定比重量级锁效率高吗?
自旋锁原地等待,会消耗资源,在线程很多,cpu切换成本过高时则效率并不高 - cas如何保证了原子性?
LOCK IF MP(nulti processor)
cpu原语支持了比较和修改的原子性,如果是多个cpu,则加LOCK
,原本是锁总线,现在是锁北桥信号
锁升级初步
对象new出来放到内存中,有四个部分:markwork
8字节,class pointer
类型指针,4字节,instance
实例数据,padding
对齐,补到对象空间被八整除为止(为了提高效率。
锁对象如何实现?
锁对象如何实现?加锁后的对象,markword里面会不一样,markword中装入了锁信息和GC和hashcode
偏向锁?
- 什么是偏向锁?
偏向锁没有经过竞争机制,只是将线程id号标记上了,是一种处理机制。 - 为什么有偏向锁?
实际使用中,可能只有一个线程在用,为了方便实现,节约时间,出现的偏向锁 - 偏向锁出现竞争怎么办?
当有线程竞争时,先进行偏向锁撤销,转化为自旋锁,占用者优先持有,其他线程以cas方式竞争,依然是记录线程id号的方式竞争锁。 - 使用偏向锁是否一定提升效率?(偏向锁为什么需要延迟4秒钟?)
明确知道存在竞争时(比如jvm启动时),无需打开偏向锁,因为锁转为自选锁也是需要占用资源的,确定空闲时(默认4s)再打开偏向锁 - lock 和 synchronized区别?
lock有公平锁,synchronized没有公平锁 - 什么是公平锁和非公平锁?
公平锁(Fair):加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得
非公平锁(Nonfair):加锁时不考虑排队等待问题,直接尝试获取锁,获取不到自动到队尾等待
公平锁和非公平锁
超线程
什么是超线程?
一个运算单元(ALU)对应两组寄存器(单核多线程),这时的两个线程被同一个运算单元服务,此为超线程
CPU缓存和内存
工业实践,3层最合适
缓存一致性问题
缓存行大小64字节
缓存一致性协议,保证缓存行的一致性
为了避免缓存行中不出现两个变量,从而规避同步成本,可以前后怼7个longInt (8字节),保证不与其他变量在一个缓存行
缓存一致性问题
intel cpu MESI协议
volatile
- 线程可见性: MESI
- 禁止重排序:cpu执行的指令时间远远小于读取内存时间,所以在等待结果之前,会将没有关联关系的后续指令拿来先执行(CPU流水线优化),这称为CPU乱序执行,禁止重排序,则会禁止这种乱序执行(禁止部分指令之间重排序,非全部指令)
对于代码影响就是,有的赋值代码的实际执行顺序,并不是严格按照代码顺序执行的,影响的其实是汇编代码,但是高级语言中也可以复现
如何实现的禁止重排序?
引入一个概念,DCL
:double check lock,类似cas
示例代码:
-
上图示例中,为什么必要加volatile?
JSR内存屏障
欢迎大家关注我的公众号
半亩房顶
网友评论