synchronized原理

synchronized

synchronized的用法参考Java中使用同步关键字synchronized需要注意的问题 - @ 小浩 - 博客园

synchronized是非公平锁

synchronized实现原理

16_深入JVM源码-monitor竞争_哔哩哔哩_bilibili

9 synchronized与锁 · 深入浅出Java多线程 (redspider.group)

 Java中的锁——Lock和synchronized - 夏末秋涼 - 博客园 (cnblogs.com)

原理总结

 1,synchronized代码块基于进入和退出monitor对象实现。代码编译后将monitorenter指令插入同步代码块的前面,monitorexit指令插入同步代码块的后面,发生异常时也会执行monitorexit指令

2,synchronized方法读取运行时常量池中方法的 ACC_SYNCHRONIZED 标志来隐式实现的

3,synchronized用的锁存储在对象头中的markword,markword中的锁标记指向的是monitor对象,

锁标记位(无锁01、轻量级锁00、重量级锁10、偏向锁01)

4,monitor对象有两个队列(EntryList、WaitSet)以及锁持有者Owner标记

synchronized的两种用法以及他们对应的字节码


package org.cc.lipiao.demo.synchronizedDemo;public class SynchronizedDemo {private static int sum;private Object obj = new Object();public static synchronized void add(){
sum++;}public synchronized void minus(){
sum--;}public void add2(){
synchronized (obj){
sum += 2;}}
}

 public static synchronized void add();descriptor: ()Vflags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZEDCode:stack=2, locals=0, args_size=00: getstatic     #4                  // Field sum:I3: iconst_14: iadd5: putstatic     #4                  // Field sum:I8: returnLineNumberTable:line 17: 0line 18: 8public synchronized void minus();descriptor: ()Vflags: ACC_PUBLIC, ACC_SYNCHRONIZEDCode:stack=2, locals=1, args_size=10: getstatic     #4                  // Field sum:I3: iconst_14: isub5: putstatic     #4                  // Field sum:I8: returnLineNumberTable:line 21: 0line 22: 8LocalVariableTable:Start  Length  Slot  Name   Signature0       9     0  this   Lorg/cc/lipiao/demo/synchronizedDemo/SynchronizedDemo;public void add2();descriptor: ()Vflags: ACC_PUBLICCode:stack=2, locals=3, args_size=10: aload_01: getfield      #3                  // Field obj:Ljava/lang/Object;4: dup5: astore_16: monitorenter7: getstatic     #4                  // Field sum:I10: iconst_211: iadd12: putstatic     #4                  // Field sum:I15: aload_116: monitorexit17: goto          2520: astore_221: aload_122: monitorexit23: aload_224: athrow25: return

可以看到当关键字用在方法时,字节码使用ACC_SYNCHRONIZED,当关键字用在代码块时,字节码使用monitorenter和monitorexit指令

java对象头和锁的状态

锁状态存储在对象头的mark word

总结下来就是:无锁时:0 01

偏向锁:线程id epoch 1 01

轻量级锁:指向栈中lock record的指针 00

重量级锁:指向互斥量的指针 10

锁状态

偏向锁

大多数情况下,锁总是由同一个线程多次获得

偏向锁的优势:减少同一线程获取锁的代价(线程进入或退出同步代码块时只需要检查偏向锁、锁标志位和线程ID即可)

在1.6之后是默认开启的,并且是在应用程序启动几秒之后开启

偏向锁处理流程:

1、第一次进入同步块并获取锁时,虚拟机将对象头偏向锁设为1,同时CAS操作(将线程ID记录到Mark Word中)

2、后面再有线程进入这个同步块时,比较当前线程的threadID和mark word中的threadID是否一致,如果一致那么无须使用CAS

3、如果threadID不一致,那么需要查看mark word中记录的线程1是否存活

4、如果没有存活,那么mark word被重置为无锁状态,当前线程可以竞争将其设置为偏向锁

5、如果存活,那么立刻查找线程1的栈帧信息,如果还是需要继续持有这个锁,那么暂停线程1,撤销偏向锁,升级为轻量级锁

6、如果线程1 不再使用该锁,那么将mark word设为无锁状态,重新偏向新的线程。

轻量级锁

1、线程1获取轻量级锁时会先把MarkWord复制一份到线程1的栈帧中的DisplacedMarkWord(用于存储锁记录的空间),然后使用CAS把对象头中的内容替换为DisplacedMarkWord的地址

2、如果在线程1复制对象头的同时(在线程1CAS之前),线程2也准备获取锁,复制了对象头到线程2的锁记录空间中,但是在线程2CAS的时候,发现线程1已经把对象头换了,线程2的CAS失败,那么线程2就尝试使用自旋锁来等待线程1释放锁。

3、如果自旋到了一定次数线程2还在自旋等待或者这时又有一个线程3过来竞争这个锁对象,那么这个时候轻量级锁就会膨胀为重量级锁。重量级锁把除了拥有锁的线程都阻塞,防止CPU空转。

重量级锁

TODO

JVM对synchronized的优化

锁消除:TODO

锁粗化:TODO

锁膨胀:无锁-》偏向锁-》轻量级锁-》重量级锁

平时写代码如何优化synchronized

减少synchronized的范围,减少synchronized的代码

降低synchronized的粒度:使用CurrentHashMap替代Hashtable等等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/57650.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot()—— swagger

零、一张图读懂swagger 懂了,这玩意就是用swagger搞出来的! 就是一个后端开发自测的东西嘛! 一、概念 存在即合理,我们看一下swagger诞生的原因:在前后端分离的架构中,前端新增一个字段,后端就…

【PDF密码】PDF文件不能打印,为什么?

正常的PDF文件是可以打印的,如果PDF文件打开之后发现文件不能打印,我们需要先查看一下自己的打印机是否能够正常运行,如果打印机是正常的,我们再查看一下,文件中的打印功能按钮是否是灰色的状态。 如果PDF中的大多数功…

Python-OpenCV 图像的基础操作

图像的基础操作 获取图像的像素值并修改获取图像的属性信息图像的ROI区域图像通道的拆分及合并图像扩边填充图像上的算术运算图像的加法图像的混合图像的位运算 获取图像的像素值并修改 首先读入一副图像: import numpy as np import cv2# 1.获取并修改像素值 # 读…

安全狗V3.512048版本绕过

安全狗安装 安全狗详细安装、遇见无此服务器解决、在windows中命令提示符中进入查看指定文件夹手动启动Apache_安全狗只支持 glibc_2.14 但是服务器是2.17_黑色地带(崛起)的博客-CSDN博客 安全狗 safedogwzApacheV3.5.exe 右键电脑右下角安全狗图标-->选择插件-->安装…

在win10上安装Docker desktop,并在docker中安装mysql

操作步骤: 安装docker 去 官网 下载安装软件;选择windows 2. 依次点击安装; 安装完成后无需登录,直接启动即可; 如果有提示需要更新wsl,执行以下命令更新: wsl --update wsl --status 查看状态 验证一下 适用命令:docker run hello-world 设置国内镜像 docker安装mysql…

不懂录音转文字转换器如何使用?来掌握这几个方法吧

作为一名忙碌的职场人士,我每天都要参加各种会议。我发现自己经常会错过会议的一些重要信息,利用录音记录又要费时间去听再转录,实在令我很头疼。直到我开始使用录音转文字这个工具,它简直像魔法一样。只要将需要转换的音频上传就…

建议收藏!独立站新手容易踩的5个坑,你中了吗?

接过很多独立站商户咨询,发现大家很容易踩几个坑,也是大家问的比较多的。 今天把印象最深的5个坑分享给大家,希望大家可以少踩坑,并且结合建议对以下几个方面进行优化,至少能保证你的独立站做到及格线上线&#xff01…

进程与线程、线程创建、线程周期、多线程安全和线程池(ThreadPoolExecutor)

目录 进程与线程线程和进程的区别是什么?线程分两种:用户线程和守护线程线程创建四种方式run()和start()方法区别:为什么调用 start() 方法时会执行 run() 方法,为什么不能直接调用 run() 方法?Runnable接口和Callable…

【Android】在AndroidStudio开发工具运行Java程序

在Android Studio开发工具中,Android系统开始就是用java语言开发的,还可以java代码来写程序,控制台,桌面应用,还可以写可调用的模块,这里讲一下创建Java程序步骤,方便入门java语言开发。 新建一…

初识网络(JavaEE初阶系列9)

目录 前言: 1.网络的发展史 1.1独立模式 1.2网络互联 1.3局域网LAN 1.4广域网WAN 2.网络通信基础 2.1IP地址 2.2端口号 3.认识协议 3.1协议分层 3.2分层的作用 3.3TCP/IP五层(或四层)模型 3.4OSI七层模型 3.5网络设备所在分层 …

快速排序和qsort函数详解详解qsort函数

💕是非成败转头空,青山依旧在,几度夕阳红💕 作者:Mylvzi 文章主要内容:快速排序和qsort函数详解 前言: 我们之前学习过冒泡排序,冒泡排序尽管很方便,但也存在一些局限性…

Sentinel整合Spring Cloud Gateway、Zuul详解

Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流。 Sentinel 1.6.0 引入了 Sentinel API Gateway Adapter Common 模块,此模块中包含网关限流的规则和自定义 API 的实体和管理逻辑: GatewayFlowRule:网关限流规则…