1.Monitor对象

Monitor对象被称为管程或者监视器锁

在Java中,每一个对象实例都会关联一个Monitor对象。

这个Monitor对象既可以与对象一起创建销毁,也可以在线程试图获取对象锁时自动生成。

当这个Monitor对象被线程持有后,它便处于锁定状态。Synchronized的基本原理就是能否获取Monitor的所有权。

monitor
ObjectMonitor() {
_header = NULL;
_count = 0; //用于记录线程获取锁的次数,成功获取到锁后count会加1,释放锁时count减1
_waiters = 0,
_recursions = 0;// 线程重入次数
_object = NULL; // 存储Monitor对象
_owner = NULL; // 持有当前线程的owner
_WaitSet = NULL;// wait状态的线程列表
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ; // 单向列表
FreeNext = NULL ;
_EntryList = NULL ;// 处于等待锁状态block状态的线程列表
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
_previous_owner_tid = 0;
}

2.对象头

在对象头的MarkWord中主要存储了对象自身的运行时数据,例如哈希码、GC分代年龄、锁状态、线程持有的锁、偏向线程ID等



当对象为偏向锁时,Mark Word存储了偏向线程的ID;

当状态为轻量级锁时,Mark Word存储了指向线程栈中Lock Record的指针;

当状态为重量级锁时,Mark Word存储了指向堆中的Monitor对象的指针。

3.锁升级

偏向锁

偏向锁的核心思想是,如果一个线程获得了锁,那么锁就进入偏向模式,此时Mark Word的结构也变为偏向锁结构,即将对象头中Mark Word的标记位改为1,并且在Mark Word中记录该线程的ID。

轻量级锁

Mark Word中的部分字节CAS更新指向线程栈中的LockRecord,如果更新成功,则轻量级锁获取成功_,记录锁状态为轻量级锁;否则,说明已经有线程获得了轻量级锁,目前发生了锁竞争(不适合继续使用轻量级锁),接下来膨胀为重量级锁。

JVM会在当前线程的线程栈中开辟一块单独的空间,里面保存指向对象锁MarkWord的指针,同时在对象锁Mark Word中保存指向这片空间的指针。上述两个保存操作都是CAS操作,如果保存成功,代表线程抢到了同步锁,就把MarkWord中的锁标志位改成00,可以执行同步代码。如果保存失败,表示抢锁失败

自旋锁

空循环一般不会执行太多次,可能是50个循环或100循环,在经过若干次循环后,如果得到锁,就顺利进入同步代码。如果还不能获得锁,那就会将线程在操作系统层面挂起,即进入到重量级锁。

重量级锁

重量级锁通过对象内部的monitor实现(见上文的MonitorObject模式)

monitor的本质是依赖于底层操作系统的MutexLock实现,操作系统实现线程间的切换是通过用户态与内核态的切换完成的,而切换成本很高

MutexLock最核心的理念就是尝试获取锁.若可得到就占有.若不能,就进入睡眠等待

4.其他概念

锁消除

JVM在编译时通过对运行上下文的描述,去除不可能存在共享资源竞争的锁,通过这种方式消除无用锁,即删除不必要的加锁操作,从而节省开销

锁膨胀

将多次连接在一起的加锁、解锁操作合并为一次,将多个连续的锁扩展成一个范围更大的锁

如果虚拟机检测到有一系列连串的对同一个对象加锁和解锁操作,就会将其合并成一次范围更大的加锁和解锁操作,即在第一次append方法时进行加锁,最后一次append方法结束后进行解锁

[Thread] Synchronized的更多相关文章

  1. java基础温习 -- Thread synchronized关键字

    synchronized 基本规则 1. 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的该“synchronized方法”或 ...

  2. 让面试官心服口服:Thread.sleep、synchronized、LockSupport.park的线程阻塞有何区别?

    前言 在日常编码的过程中,我们经常会使用Thread.sleep.LockSupport.park()主动阻塞线程,或者使用synchronized和Object.wait来阻塞线程保证并发安全.此时 ...

  3. Java并发编程:synchronized

    Java并发编程:synchronized 虽然多线程编程极大地提高了效率,但是也会带来一定的隐患.比如说两个线程同时往一个数据库表中插入不重复的数据,就可能会导致数据库中插入了相同的数据.今天我们就 ...

  4. JAVA笔记 之 Thread线程

    线程是一个程序的多个执行路径,执行调度的单位,依托于进程存在. 线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间也叫做线程栈,是在建立线程时由系统分配的,主要用来保存线程内部 ...

  5. 【转】Java并发编程:synchronized

    一.什么时候会出现线程安全问题? 在单线程中不会出现线程安全问题,而在多线程编程中,有可能会出现同时访问同一个资源的情况,这种资源可以是各种类型的资源:一个变量.一个对象.一个文件.一个数据库表等,而 ...

  6. 高并发编程基础Synchronized与Volatile

    关键字Synchronized: 当使用Synchrnized (o) ,锁定 o 的时候,锁定的是 o 指向的堆内存中 new 出来的对象,而非 o 引用,当锁定 o 以后,一旦 o 指向了其他对象 ...

  7. Java并发编程(四)synchronized

    一.synchronized同步方法或者同步块 在了解synchronized关键字的使用方法之前,我们先来看一个概念:互斥锁,顾名思义:能到达到互斥访问目的的锁. 举个简单的例子:如果对临界资源加上 ...

  8. 多线程之synchronized

    Java并发编程:synchronized 虽然多线程编程极大地提高了效率,但是也会带来一定的隐患.比如说两个线程同时往一个数据库表中插入不重复的数据,就可能会导致数据库中插入了相同的数据.今天我们就 ...

  9. 05 synchronized

    转载自:  Java并发编程:synchronized http://www.cnblogs.com/dolphin0520/p/3923737.html 前文中也有相关的详细描述:02 如何创建线程 ...

随机推荐

  1. LuoguP5201 [USACO19JAN]Shortcut(最短路树)

    字典序?建树时从小枚举,用\(Dijkstra\)的血泪建好树,\(size\)大小决定贡献 #include <iostream> #include <cstdio> #in ...

  2. Spring源码 11 IOC refresh方法6

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  3. Excel 查找函数(二):VLOOKUP

    函数讲解 [语法]VLOOKUP(lookup_value, table_array, col_index_num, [range_lookup]) [参数]函数一个有四个参数,其中有三个必填参数:一 ...

  4. Excelize 2.3.2 发布,Go 语言 Excel 文档基础库,2021 年首个更新

    Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准.可以使用它来读取.写入由 Microsoft Exc ...

  5. [CF1498D] Bananas in a Microwave (DP)

    题面&翻译 题解 虽然 m m m 很大,但是 n n n 很小,因此题目允许我们在 O ( n m ) O(nm) O(nm) 以内解决这道题. 定义一个 dp[i][j]=0/1 ? 如果 ...

  6. OpenJ_Bailian - 3424 Candies (差分约束)

    题面 During the kindergarten days, flymouse was the monitor of his class. Occasionally the head-teache ...

  7. 「题解报告」Blocks

    P3503 Blocks 题解 原题传送门 思路 首先我们可以发现,若 \(a_l\) ~ \(a_r\) 的平均值大于等于 \(k\) ,则这个区间一定可以转化为都大于等于 \(k\) 的.我们就把 ...

  8. 给ShardingSphere提了个PR,不知道是不是嫌弃我

    说来惭愧,干了 10 来年程序员,还没有给开源做过任何贡献,以前只知道嘎嘎写,出了问题嘎嘎改,从来没想过提个 PR 去修复他,最近碰到个问题,发现挺简单的,就随手提了个 PR 过去. 问题 问题挺简单 ...

  9. js函数( 普通函数、箭头函数 ) 内部this的指向

    - 普通函数   | 具名普通函数.匿名普通函数,在不作为对象的属性值的情况下,其内部的 this 总是指向代码运行环境下的全局对象 ( 例如,浏览器中的 window ). 示例: (functio ...

  10. 跟羽夏学 Ghidra ——调试

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...