Synchronized同步锁的优化方法 待完工

news2024/11/26 2:42:00

Synchronized 和后来出的这个lock锁的区别

在并发编程中,多个线程访问同一个共享资源时,我们必须考虑如何维护数据的原子性。在
JDK1.5 之前,Java 是依靠 Synchronized 关键字实现锁功能来做到这点的。Synchronized 是 JVM 实现的一种内置锁,锁的获取和释放是由 JVM 隐式实现。

到了 JDK1.5 版本,并发包中新增了 Lock 接口来实现锁功能,它提供了与 Synchronized
关键字类似的同步功能,只是在使用时需要显示获取和释放锁

Lock 同步锁是基于 Java 实现的,而 Synchronized 是基于底层操作系统的 Mutex Lock
实现的,每次获取和释放锁操作都会带来用户态和内核态的切换,从而增加系统性能开销

因此,在锁竞争激烈的情况下,Synchronized 同步锁在性能上就表现得非常糟糕,它也常
被大家称为重量级锁。

1.6以后呢对这个Synchronized 锁进行了升级,引入了锁升级,某些程度上来说呢。再某些业务场景已经超过了lock。

这里再次生明Synchronized 是关键字,而lock是通过是西安这个lock接口来实现这个所功能的。

Synchronized 底层原理 ,也就是他的同步原理

通常 Synchronized 实现同步锁的方式有两种,一种是修饰方法,一种是修饰方法块。以
下就是通过 Synchronized 实现的两种同步方法加锁的方式:

 javac -encoding UTF-8 SyncTest.java // 先运行编译 class 文件命令

javap -v SyncTest.class // 再通过 javap 打印出字节文件

通过以上命令去反编译出这个文件的字节码文件可以看到

你会发现:Synchronized 在修饰同步代码块时,是由 monitorenter和 monitorexit 指令来实现同步的。进入 monitorenter 指令后,线程将持有 Monitor 对象,退出 monitorenter 指令后,线程将释放该 Monitor 对象。注意修饰的代码块

而同步方法的字节码中,你会发现:当 Synchronized 修饰同步方法时,并没有发
monitorenter 和 monitorexit 指令,而是出现了一个 ACC_SYNCHRONIZED 标志。

这是因为 JVM 使用了 ACC_SYNCHRONIZED 访问标志来区分一个方法是否是同步方法

当方法调用时,调用指令将会检查该方法是否被设置 ACC_SYNCHRONIZED 访问标志。
如果设置了该标志,执行线程将先持有 Monitor 对象,然后再执行方法。在该方法运行期
间,其它线程将无法获取到该 Mointor 对象,当方法执行完成后,再释放该 Monitor 对
象。

 再来看看 Synchronized 修饰方法是怎么实现锁原理的。

JVM 中的同步是基于进入和退出管程(Monitor)对象实现的。每个对象实例都会有一个
Monitor,Monitor 可以和对象一起创建、销毁。

当多个线程同时访问一段同步代码时,多个线程会先被存放在 EntryList 集合中,处于
block 状态的线程,都会被加入到该列表。接下来当线程获取到对象的 Monitor 时,
Monitor 是依靠底层操作系统的 Mutex Lock 来实现互斥的,线程申请 Mutex 成功,则持
有该 Mutex,其它线程将无法获取到该 Mutex。

注意阅读下图

 如果线程调用 wait() 方法,就会释放当前持有的 Mutex,并且该线程会进入 WaitSet 集合
中,等待下一次被唤醒。如果当前线程顺利执行完方法,也将释放 Mutex。

这里插播一下 wait和sleep都释放锁码?好像写代码的时候遇到过

 因 Monitor 是依赖于底层的操作系统实现,存在用户态与内核态之间的切换,所以增加了性能开销。

锁升级优化

为了提升性能,JDK1.6 引入了偏向锁、轻量级锁、重量级锁概念,来减少锁竞争带来的上
下文切换,而正是新增的 Java 对象头实现了锁升级功能。
当 Java 对象被 Synchronized 关键字修饰成为同步锁后,围绕这个锁的一系列升级操作都
将和 Java 对象头有关。

Java 对象头

在 JDK1.6 JVM 中,对象实例在堆内存中被分为了三个部分:对象头、实例数据和对齐填
充。其中 Java 对象头由 Mark Word、指向类的指针以及数组长度三部分组成

Mark Word 记录了对象和锁有关的信息。Mark Word 在 64 位 JVM 中的长度是 64bit

 锁升级功能主要依赖于 Mark Word 中的锁标志位和释放偏向锁标志位,Synchronized 同
步锁就是从偏向锁开始的,随着竞争越来越激烈,偏向锁升级到轻量级锁,最终升级到重量
级锁。

1. 偏向锁

偏向锁主要用来优化同一线程多次申请同一个锁的竞争。在某些情况下,大部分时间是同一
个线程竞争锁资源,例如,在创建一个线程并在线程中执行循环监听的场景下,或单线程操
作一个线程安全集合时,同一线程每次都需要获取和释放锁,每次操作都会发生用户态与内
核态的切换。

 再自己的同步代码块里加锁,同步代码块有全局变量,我们枷锁,让它不被别的线程修改

偏向锁的作用就是,当一个线程再次访问这个同步代码或方法时,该线程只需去对象头的
Mark Word 中去判断一下是否有偏向锁指向它的 ID,无需再进入 Monitor 去竞争对象
了。

当对象被当做同步锁并有一个线程抢到了锁时,锁标志位还是 01,“是否偏向锁”标
志位设置为 1,并且记录抢到锁的线程 ID,表示进入偏向锁状态。

一旦出现其它线程竞争锁资源时,偏向锁就会被撤销。偏向锁的撤销需要等待全局安全点,
暂停持有该锁的线程,同时检查该线程是否还在执行该方法,如果是,则升级锁,反之则被
其它线程抢占。

下图中红线流程部分为偏向锁获取和撤销流程:

 

 

 

偏向锁这个设计到一个调优 高并发

在高并发场景下,当大量线程同时竞争同一个锁资源时,偏向锁就会被撤销,发生
stop the world 后, 开启偏向锁无疑会带来更大的性能开销,这时我们可以通过添加 JVM
参数关闭偏向锁来调优系统性能

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【枚举】CF1706 C

有人一道1400写了一个小时 Problem - C - Codeforces 题意: 思路: 首先先去观察样例: 很显然,对于n是奇数的情况,只有一种情况,直接操作偶数位就好了 主要是没搞清楚n是偶数的情况 其实有个小技巧&…

前沿分享-鱼形机器人

可能并不太前沿了,是21年底的新闻了,但是看见了就顺便发一下吧。 大概就是,通过在pH响应型水凝胶中编码不同的膨胀速率而构建了一种环境适应型变形微机器人,让微型机器人直接向癌细胞输送药物从而减轻药物带来副作用。 技术原理是&#xff0c…

第五章 树与二叉树

一、数据结构定义 二叉树的顺序存储结构二叉树的链式存储结构(即二叉链表)(因为有两个指针所以是二叉链表,如果再加一个指向父节点的指针就是三叉链表)typedef struct BTNode{ // BT即Binary Tree,二叉树i…

Reinforcement Learning with Code 【Code 4. DQN】

Reinforcement Learning with Code 【Code 4. DQN】 This note records how the author begin to learn RL. Both theoretical understanding and code practice are presented. Many material are referenced such as ZhaoShiyu’s Mathematical Foundation of Reinforcement…

C++笔记之从数组指针到函数数组指针(使用using name和std::function)

C笔记之从数组指针到函数数组指针(使用using name和std::function) 参考笔记: C之指针探究(三):指针数组和数组指针 C之指针探究(十三):函数指针数组 C之指针探究(二):一级指针和一维数组 C之指针探究(十一):函数名的…

HCIP VLAN--Hybrid接口

一、VLAN的特点 1、一个VLAN就是一个广播域,所以在同一个VLAN内部,计算机可以直接进行二层通信;而不同VLAN内的计算机,无法直接进行二层通信,只能进行三层通信来传递信息,即广播报文被限制在一个VLAN内。 …

数字人现身大运会,怎么以动作捕捉技术助推运动与文博相结合

中国移动动感地带数字人橙络络,作为数智体验官以元宇宙的视角,带领观众沉浸式体验大运会,以极具科技和未来的数字人,对外传递大运青春风采,并且数字人橙络络还对大运会的赛事、活动进行了科普、讲解以及表演当地特色才…

Cpp学习——string(2)

目录 ​编辑 容器string中的一些函数 1.capacity() 2.reserve() 3.resize() 4.push_back()与append() 5.find系列函数 容器string中的一些函数 1.capacity() capacity是string当中表示容量大小的函数。但是string开空间时是如何开的呢?现在就来看一下。先写…

Postgresql15安装插件madlib2.0

madlib2.0简介 Apache MADlib madlib使用指南 MADlib: Main Page madlib安装 Installation Guide - Apache MADlib - Apache Software Foundation 准备 cmake 3.5.2及以上版本python3.9postgresql15,源码编译时必须指定 –with-pythonpostgresql插件plpython3u 源…

【Autolayout自动布局介绍2 Objective-C语言】

一、好,我们继续来介绍Autolayout 1.好,那么,我们接下来,开始上课了, 刚才,给大家介绍了一下,我们就是屏幕布局里面,用到的,主要就是这四个按钮: 1)第一个:是用来做对齐的 2)第二个:是用来做固定的 3)第三个:是用来解决自动布局中出现的一些问题的 4)第四…

元组是什么,python怎么使用元组

目录 引言 元组的概念 作用和优势 元组的应用 Python中如何使用元组 注意事项 总结 引言 在Python编程语言中,元组(Tuple)是一种不可变的数据结构,它允许我们以有序且不可修改的方式存储多个元素。与列表不同,…

简单游戏截图_可控截取内容2

一个需求 我需要在场景中截取不同层级的截图(如只截模型或只截UI或只截外部相加看到的画面 或全都截或和Shader配合呈现人眼夜视仪热成像的画面切换) 将截图排到列表中,在场景UI中展示出来 如何做 相机要能够看到不同的画面 将当前帧画面存储下来 将存储的画面展示出…

利用文档管理系统软件实现信息共享与知识沉淀

在当今信息的时代,各个企业和组织面临着大量的信息管理和知识沉淀的问题。为了更好地实现信息共享和知识沉淀,许多企业开始使用文档管理软件,该软件通过整合和管理各种文档,并提供强大的搜索和分享功能,有效促进了信息…

Java容器之Stack和Deque

Java容器之Stack和Deque 目录概述需求: 设计思路实现思路分析1.Java中Deque和Stack都是用于实现栈(stack)数据结构的类,但它们有一些区别。2.实现方式不同3.用途不同 拓展实现 参考资料和推荐阅读 Survive by day and develop by …

代驾小程序怎么做

代驾小程序是一款专门为用户提供代驾服务的手机应用程序。它具有以下功能: 1. 预约代驾:代驾小程序允许用户在需要代驾服务时提前进行预约。用户可以选择出发地点、目的地以及预计用车时间,系统会自动匹配最合适的代驾司机,并确保…

Ref从入门到入土

首先做个对比: 功能一:引用一个值做持久化记忆 场景:清除定时器 import { useRef } from "react" import { useState } from "react" // ref:1.引用一个值 做持久化记忆 // let num useRef(1) // console.log(num.cur…

Pandaer的iPhone手机壳

哇塞,Pandaer的设计太棒了!手机壳的花样多到让我眼花缭乱,好多系列设计都很有意思,让人有集齐的冲动。我最近入手了几个iPhone的手机壳,它有亮色和透明的款式,亮色的壳内部也是亮的,因为手机壳全…

宝塔一键安装包安装魔众XX系统

1 环境安装 1.1 一定先看 在阅读本文档安装系统时,请确保您已经 熟练掌握 如何使用 apache 或 nginx 的进行网站系统的配置方法。 如果您 不是很了解 或 了解甚少,请直接购买我们的 付费安装服务,同时把服务器信息、需要安装的系统源码提供给…

8月1日上课内容 第一章web基础与http协议

dns与域名 网络是基于tcp/ip协议进行通信和连接的 应用层--传输层---网络层----数据链路层-----物理层 ip地址,我们每一台主机都有一个唯一的地址标识(固定的ip地址),区分用户和计算机通信。 ip地址:32位二进制数组成的,不方便记忆 192.168.…

Android Ble蓝牙App(三)特性和属性

Ble蓝牙App(三)特性使用 前言正文一、获取属性列表二、属性适配器三、获取特性名称四、特性适配器五、加载特性六、显示特性和属性七、源码 前言 在上一篇中我们完成了连接和发现服务两个动作,那么再发现服务之后要做什么呢?发现服…