栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

六、锁原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

六、锁原理

一、轻量级锁 1. 应用场景
  • 一个对象虽被多个线程访问,但访问时间是错开的,不存在竞争
  • 轻量级锁对使用者 是透明的, 语法:syncronized
2. 锁重入代码
  • 对于两个方法,用同一个对象进行加锁
package com.dreamer.multithread.day03;

public class Demo01 {
    public static void main(String[] args) {
        new Thread(() -> Student.method01()).start();
    }
}

class Student {
    private static Object obj = new Object();

    public static void method01() {
        synchronized (obj) {
            System.out.println("first method working");
            method02();
        }
    }

    public static void method02() {
        synchronized (obj) {
            System.out.println("second method working");
        }
    }
}
3. 加锁流程 3.1 创建锁纪录
  • 创建锁记录(Lock Record)对象,每个线程的栈桢都会包含一个锁记录的结构,内部可以存储锁定对象的Mark Word

3.2 cas交换
  • 让锁记录中Object reference指向锁对象,并尝试用cas替换Object中的 Mark Word, 将Mark Word 中的值存入
  • Object中,01代表无锁状态
  • 如果cas交换成功,对象头中存储锁记录地址和状态00,表示由该线程给对象加锁
  • Object中01就会变为00,代表轻量级锁

3.2 cas失败情况
  • 锁膨胀:如果是其他线程已经持有了该Object 的轻量级锁,表明有竞争,进入锁膨胀过程
  • 锁重入:如果是自己执行了synchronized锁重入,那么再添加一个Lock Record作为重入计数
  • 重入: 通过lock record和00,能发现是自己这个线程已经持有这个锁了,就会将锁记录变为null
3.3 解锁
  • 当退出synchronized代码块时候,如果有取值为null的锁记录,表示有重入,这时重制锁记录,表示重入计数减一
  • 当退出synchronized代码块时,锁记录不为null,这时使用cas将Mark Word的值恢复给对象头
  • 成功则代表解锁成功; 失败说明轻量级锁进入了锁膨胀或者已经升级为重量级锁
二、锁膨胀
  • 如果在尝试轻量级加锁的过程中,CAS操作无法成功,可能是因为:其他线程为此对象加上了轻量级锁(有竞争),这时需要进行锁膨胀,将其他线程的锁变为重量级锁


  • 当Thread-0 退出同步块时,使用cas将Mark Word的值恢复给对象头,失败进入重量级解锁流程
  • 按照Monitor地址找到Monitor对象,设置Owner为null,唤醒EntryList中BLOCKED线程
三、重量级锁—自旋优化
  • 重量级锁竞争的时候,还可以使用自旋来进行优化,如果当前线程自旋成功(即这个时候锁线程颐景退出了同步快,释放了锁),这时线程就可以避免阻塞
1. 自旋成功

2. 自旋失败

智能自旋: 
1. java6之后,自旋是自适应的,比如对象刚刚的一次自旋成功,就认为自旋成功的概率大,就会多自旋几次
   反之,就少自旋几次甚至不自旋
2. 自旋会占用cpu时间,单核自旋就是浪费,多核自旋才有意义
3. java7之后不能控制是否开启自旋功能
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/281294.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号