JUC——Synchronized原理

打印 上一主题 下一主题

主题 1025|帖子 1025|积分 3075

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1、轻量级锁

   轻量级锁的使用场景:  假如一个对象虽然有多线程访问,但多线程访问的时间是错开的(也就是没有竞争),那么可以使用轻量级锁来优化。    轻量级锁对使用者是透明的,即语法仍是synchronized 。     假设现在有两个方法同步块,使用同一个对象加锁:    static final Object obj = new Object(); public static void method1(){ synchronized(obj){ //同步块A method2(); } } public static void method2(){ synchronized(obj){ //同步块 } }   

  • 创建锁记载对象,每个线程的栈帧都会包含一个所记载的结构,内部可以存储锁定对象的Mark Word。
   

  • 让锁记载中的Object reference指向锁对象,并尝试用cas替换Object的Mark Word,将Mark Word 的值存入锁记载
   
   

  • 假如cas替换乐成,对象头中存储了锁记载地址和状态 00,表示由该线程给对象加锁:【01 表示轻量级锁
   
   

  • 假如CAS失败,有两种情况   

    • 假如是其他线程已经持有了该Object的轻量级锁,这是表明有竞争,进入锁膨胀过程
    • 假如是自己实行了synchronized锁重入,那么在添加一条Lock Record作为重入的计数

   
   

  • 当退出 Synchronized 代码块(解锁时)假如有取值为null的所记载,表示有重入,这时重制锁记载,表示重入计数减一
   

  • 当退出synchronized 代码块时锁记载部位null,这时使用 CAS 将 Mark Word 的值规复给对象头   

    • 乐成,则解锁乐成
    • 失败,说明轻量级锁进行了锁膨胀或已经升级为重量级锁,进入重量级解锁流程

   2、锁膨胀

   假如在尝试加轻量级所的过程中,CAS操作无法乐成,这时一种情况就是有其他线程为此对象加上了轻量级锁(有竞争),这时需要进行锁膨胀,将轻量级锁变为重量级锁。   

  • 当Thread-1进行轻量级加锁时,Thread-0 已经对该对象加了轻量级锁
   
   

  • 这时Thread-1 进行轻量级加锁失败,进入锁膨胀流程   

    • 即为 Object 对象申请Monitor锁,让Object指向重量级锁地址
    • 然后自己进入 Monitor 的EntryList BOLCKED

   
   

  • 当Thread-0 退出同步块解锁时,使用CAS将Mark Word 的值规复给头对象,失败。这时会进入重量级锁解锁流程,即按照Monitor 地址找到Monitor对象,设置Owner为null,叫醒EntryList中BLOCKED线程
  3、自旋优化

   重量级锁竞争的时候,还可以使用自旋来进行优化,假如当前线程自旋乐成(即这时候持锁线程已经推出了同步块,开释了锁),这时当前线程就可以制止阻塞。    【阻塞意味着需要进行一次上下文切换】   
    自旋的时候需要使用CPU,适合多核CPU,假如只有单核这时CPU在实行获取到锁的线程,自旋就没有意义了。   
   

  • 获取锁:假如锁是可用的,线程会获取锁并继承实行。
  • 阻塞状态:假如锁被其他线程持有,当前线程会进入阻塞状态,等候锁的开释。
  • 线程切换:线程调度器会选择其他就绪状态的线程来实行,以充分使用CPU资源。
     

  • 在Java6之后自旋锁是自顺应的,好比对象刚刚的一次自旋操作乐成过,那么以为这次自旋乐成的大概性会高,就多自旋反复;反之,就少自旋乃至不自旋,总之,比较只能。
  • 自旋会占用CPU时间,单核CPU自选就是浪费,多核CPU自旋才能发挥优势
  • Java 7之后不能控制是否开启自选功能。
  4、偏向锁

   偏向锁,顾名思义,它会偏向于第一个访问锁的线程
  假如在运行过程中,同步锁只有一个线程访问,不存在多线程争用的情况,则线程是不需要触发同步的,这种情况下,就会给线程加一个偏向锁。线程第二次到达同步代码块时,会判断此时持有锁的线程是否就是自己,假如是则正常往下实行。由于之前没有开释锁,这里也就不需要重新加锁。假如自始至终使用锁的线程只有一个,很明显偏向锁几乎没有额外开销,性能极高。
假如在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会消除它身上的偏向锁,将锁规复到标准的轻量级锁。偏向锁通过消除资源无竞争情况下的同步原语,进一步提高了程序的运行性能。一旦有第二个线程参加锁竞争,偏向锁就升级为轻量级锁(自旋锁)。升级为轻量级锁的时候需要取消偏向锁,取消偏向锁的时候会导致STW(stop the word)操作;
   锁竞争:假如多个线程轮流获取一个锁,但是每次获取锁的时候都很顺利,没有发生阻塞,那么就不存在锁竞争。只有当某线程尝试获取锁的时候,发现该锁已经被占用,只能等候其开释,这才发生了锁竞争。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81429

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表