马士兵多线程直播笔记(上)

线程与进程

  • 进程:操作系统分配资源的基本单位
  • 线程:CPU调度(执行)的基本单位。共享进程的资源。

  一个CPU同一时间只能执行一个线程,表象是线程切换(Context Switch)。对CPU来说,寄存器存数、ALU计算、PC(程序计数器)记录位置。

线程切换过程

  线程时间结束后,当前整个状态(PC、寄存器等)全部拿出去放到缓存或者内存中,也成为保护现场

线程一定是越多越好吗

  不,过多线程的切换需要资源较多。

JVM级别线程

  Class启动的Thread,JVM级别线程,对应操作系统内核线程

  当然JVM没有规定一一对应关系,但是HotSpot实现,JVM线程:内核线程=1:1。可参见:https://www.cnblogs.com/MrSaver/p/12987454.html。还是一种线程模型是,用户级别线程,通过虚拟的PC、虚拟寄存器,管理属于用户空间的线程,轻量级的线程——协程,纤程。短计算场景下优于内核线程

注:JDK1.2之前,Synchronized由OS帮忙管理,非常的重量级锁。

锁的本质

  锁定对象,可参见:https://www.cnblogs.com/MrSaver/p/13024132.html。锁上面有等待队列,以实现调度。

CAS

  这样的代码,结果一定不是一百万。注意,加Volatile没有用!

    

  CAS(Compare And Swap),最底层是native代码,由操作系统负责实现。乐观锁,马士兵称之为自旋锁,本质死循环,但是一定能有执行成功的时候!

  

问1:如何处理ABA问题?

答:加版本处理

问2:为什么会比重量级锁效率高?

答:伪命题,未必,即使经历过用户空间的优化,具体问题具体分析。

  自旋是消耗CPU资源的,如果锁的时间长,或者自旋线程多,CPU会被大量消耗。重量级锁有等待队列,所有拿不到所得进入等待队列,不需要消耗CPU资源。 

问3:原子性如何实现!

答:硬件指令集提供,见下代码!

  

  进入之后,汇编命令:CMPXCHG。

  

JOL(Java Object Layout)与锁

  对象的内存布局打印信息如下:

  

  当我们给对象加Synchronized锁后,再打印JOL信息:

  

  MarkWord锁内容具体如下:

  

偏向锁

  偏向锁也是JDK1.6中引入的一项锁优化。目的是在无竞争的情况下把整个同步都消除掉,包括CAS操作。这个锁会偏向于第一个获得它的线程,如果在接下来的执行过程中,该锁没有被其他线程获取,则持有偏向锁的线程讲永远不需要进行同步。但是一旦有另外一个线程去尝试获取这个锁时,偏向模式就宣告结束,撤销偏向后恢复到未锁定(01)或轻量级锁定(00)状态。

  在统计学分析下,一个锁大多数情况下只有一个线程再用,比如Vector、StringBuffer很多方法都会有Synchronized,但是通常业务下只有一个线程在用。

锁升级过程

  总体路径:无锁——偏向锁——自旋锁——重量级锁。

  多线程竞争下,偏向锁(放在MarkWord)撤销先变为自旋锁(CAS方式),重度竞争的情况下,线程较多的情况下,升级为重量级锁。

  

 

posted @ 2020-06-25 22:11  子烁爱学习  阅读(812)  评论(0编辑  收藏  举报