JavaEE初阶-多线程进阶1

文章目录

  • 前言
  • 一、常见的锁策略
    • 1.1 乐观锁与悲观锁
    • 1.2 重量级锁与轻量级锁
    • 1.3 自旋锁与挂起等待锁
    • 1.4 可重入锁与不可重入锁
    • 1.5 公平锁与非公平锁
    • 1.6 互斥锁与读写锁
  • 二、synchronized的优化策略
    • 2.1 锁升级
    • 2.2 锁消除
    • 2.3 锁粗化


前言

多线程进阶的内容在面试中容易考,但是在工作开发中很少用到。


一、常见的锁策略

并非局限于java,其它变成语言或者其它系统级别的组件,但凡涉及到锁,都和接下来谈到的锁策略有一定关系。

1.1 乐观锁与悲观锁

加锁的时候要预测发生冲突的概率是大还是小,如果说加锁后预测冲突发生概率小,要做的善后工作少,加锁的开销小(时间、系统资源),那么这把锁就是乐观锁。如果说加锁后预测冲突发生概率大,要做的善后工作多,加锁的开销大(时间、系统资源),那么这把锁就是悲观锁。
那么java中的我们学过很多的synchronized是悲观锁还是乐观锁?
事实上synchronized既是悲观锁也是乐观锁,它是一种自适应的锁,它能够统计出当前锁冲突的次数,进行判定锁冲突的概率低还是高,当冲突概率高时就按照悲观锁的处理方式来执行(速度更快),当冲突概率低时就按照乐观锁的处理方式来执行(做的工作更多)。
乐观锁一般只涉及到用户态的操作,要做的工作少。悲观锁往往是要通过内核完成一些操作,要做的工作就多。

1.2 重量级锁与轻量级锁

加锁的过程做的多指的就是重量,加锁的过程中做的少就是轻量,因此一般来说乐观锁就是轻量级锁,悲观锁就是重量级锁,实际交流过程中这两组概念可能会混着用。

1.3 自旋锁与挂起等待锁

自旋锁是轻量级锁的一种典型的实现方式。
在这里插入图片描述
如图cpu在空转,陷入一种忙等的状态。通过消耗资源来确保第一时间获取到锁。
挂起等待锁是重量级锁的一种典型实现方式,借助系统的线程调度机制,当尝试加锁锁被占用了就会出现锁冲突,此时尝试加锁的线程就会被挂起(阻塞状态),此时这个线程就不会参与调度了。直到要加的锁被释放后,系统才会重新唤醒这个线程去重新获取锁。从这个过程可以看出,挂起等待是很慢的,因为线程一旦阻塞起来这个过程是不可控的,可能会经历很长的时间,但是这个方法对cpu的使用很少。
java中的synchronized轻量锁使用自旋锁实现(基于CAS机制实现),重量锁使用挂起等待锁实现(调用系统API,通过内核)。

1.4 可重入锁与不可重入锁

java中的synchronized就是可重入锁,一个线程,针对这把锁连续加锁两次不会产生死锁。不可重入锁就相反,针对一把锁连续加锁两次就会产生死锁。

1.5 公平锁与非公平锁

公平锁指的就是严格按照先来后到的顺序来获取锁,哪个线程等待的时间长就先得到锁。非公平锁就是指若干个线程各凭本事随机获取得到锁,这和线程的等待顺序无关,java中的synchronized就属于非公平锁。
这里不禁提出一个问题,什么叫公平?我按照先来后到的顺序是一种公平,我每个线程一起竞争得到锁的概率随机也不失为一种公平。这里其实涉及到历史的问题,因为设计这个概念的大佬就是这样描述公平锁的,所以我们也只能听大佬的了。

1.6 互斥锁与读写锁

互斥锁的概念比较简单,java中的synchronized就是互斥的。
读写锁是一个比较特殊的锁,我们之前学过数据库中的事务的隔离性里面给读加锁给写加锁,这里的读写锁跟那个不一样,在事务那里加锁降低了并发能力,但在这里加锁是为了提高并发能力。java中的读写锁是这样设定的:
(1)读锁和读锁不会产生互斥。
(2)写锁和写锁之间会产生互斥。
(3)读锁和写锁之间会产生互斥。
我在这里说一下我的理解,读写锁就是将锁细化了,当在多线程的情况下读取数据是不会产生线程安全问题的,因此读锁之间无需互斥,这样降低了锁冲突的概率从而提高了并发能力。相反在多线程的情况下写数据是有问题的,因此写锁之间需要互斥来保证线程安全。

二、synchronized的优化策略

synchronized既是悲观锁也是乐观锁,既是重量级锁也是轻量级锁,轻量级锁的实现基于自旋锁,重量级锁的实现基于挂起等待锁,是可重入锁,不是读写锁,是非公平锁。

2.1 锁升级

synchronized这种自适应锁的锁升级的过程如下图:
在这里插入图片描述
在这个过程中主要要理解一下偏向锁。
首次使用synchronized给对象进行加锁时不是真的加锁,而是做一个标记(非常轻量非常快,几乎没有开销),这就是偏向锁。如果一直没有别的线程尝试给这个对象加锁,那么就会一致保持这种偏向锁的状态直至释放解锁。(解锁也就是改变标记,也几乎没有开销)上述过程中就相当于没有任何加锁操作,速度非常快。但是如果在偏向锁的状态下也有别的线程尝试给该对象加锁,那么偏向锁就会立即升级为轻量级锁从而发生互斥保证线程安全。偏向锁就是“懒”这个字的具体体现,能不加锁就不加锁,能晚加锁就晚加锁,这样就能在很多时候把开销省下来。
上述的锁的升级过程对一个锁对象来说是不可逆的,只能升级不能降级。

2.2 锁消除

锁消除是一种编译器优化策略,你代码中有加锁操作,编译器以及JVM会对其进行判定,看这个地方是否真的需要加锁,如果不需要就会自动将加锁操作给优化掉。最典型的例子就是在一个线程内使用synchronized。编译器优化前和优化后的效果需要一致,所以这里是比较保守的,作用有限,本质上也是为了在程序员感知不到的情况下去提高效率。

2.3 锁粗化

首先了解一个概念就是锁粒度,指的就是在加锁的范围内包含的代码越多就认为锁的粒度越粗,反之就是锁的粒度越细。
锁的粗化也是一种优化策略,比如说有些逻辑中需要频繁的加锁,此时我们就可以进行锁的粗化,将多段逻辑包含到一个锁当中。
在这里插入图片描述

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

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

相关文章

好用的Tipard 蓝光转换器 (Tipard Blu-ray Converter) mac&win

Tipard Blu-ray Converter 是一款令人惊叹的蓝光解决方案软件,可将蓝光光盘/文件夹转换为 1:1 质量的数字格式,速度提高 30 倍,用于 4K UHD 和 1080p 高清视频。它可以将蓝光光盘和文件夹中的蓝光电影转换为MKV、MP4、WMV、MOV、AVI、FLV、VO…

汽车EDI:IAC Elmdon EDI 对接指南

近期收到客户C公司的需求,需要与其合作伙伴IAC Elmdon建立EDI连接,本文将主要为大家介绍IAC Elmdon EDI 对接指南,了解EDI项目的对接流程。 项目需求 传输协议:OFTP2 IAC Elmdon 与其供应商之间使用的传输协议为OFTP2。OFTP2是…

如何管理研发人员

在日益激烈的市场竞争中,企业的核心竞争力往往取决于其技术创新能力和研发实力。然而,随着企业研发的深入和技术的积累,研发人员泄密的风险也愈发严重。如何防止研发人员泄密,已经成为企业面临的重要问题。本文将从加强员工保密意…

财富加速器!AI智能无人直播,矩阵操作引领您卖货、卖团购券、拓客,助力财富梦想实现!

财富加速器!AI智能无人直播,矩阵操作引领您卖货、卖团购券、拓客,助力财富梦想实现! 在当今数字化时代,AI智能技术正以惊人的力量催生新的商机,为经济增长注入源源不断的动力。如果您渴望实现财富梦想&…

学习笔记:使用Ollama项目快速本地化部署Qwen 1.5模型

Ollama简介 Ollama是一个开源框架,专门设计用于在本地运行大型语言模型。它的主要特点是将模型权重、配置和数据捆绑到一个包中,从而优化了设置和配置细节,包括GPU使用情况,简化了在本地运行大型模型的过程。Ollama支持macOS和Li…

利用宝塔面板搭建nodejs网站(不使用pm2)

利用宝塔面板搭建nodejs网站(不使用pm2) 1. 准备代码文件2. 将代码上传至云主机3. 云主机配置3.1 绑定域名3.2 利用面板配置node环境3.3 利用面板增加node项目 4. 打开端口 暂时只演示http的。https类似,需要添加证书。 1. 准备代码文件 清单…

Linux---在Xshell上配置软件包管理器yum

一、什么是yum 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的软…

宝塔助手是以宝塔Linux面板提供的API开发的一款可以随时随地管理服务器的APP

【软件介绍】手机操控云服务器的神器软件,本人亲测在用,好用极了! 【软件名称】宝塔助手 【软件包名】com.lensyn.zsbt 【软件版本】1.4.1 【软件大小】29.00M 【适用系统】安卓 【软件特色】宝塔助手是以宝塔Linux面板提供的API开发的一款可…

设计模式分享

2. 策略模式 2.1 定义:策略模式定义了家族算法,分别封装起来(这些算法完成的都是相同的工作,只是实现不同),它可以用相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。此模式…

Python实战开发及案例分析(25)—— 爬山算法

爬山算法(Hill Climbing)是一种启发式搜索算法,常用于解决优化问题。它的核心思想是从一个初始解开始,不断朝着增益最大的方向移动,直到达到局部最优解。 实现步骤 从初始解开始。在当前解的邻域中找到一个更好的解。…

LeetCode109:组合总和Ⅳ

题目描述 给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围。 解题思想 使用完全背包 代码 /*dp[i]:表示装满容量为i的背包有dp[i]种方…

高通QCS6490开发(二)AI板卡接口

QCS6490是高通公司针对高端物联网终端而优化的SoC,在性能和功耗上有最优的平衡。《高通QCS6490 AIoT应用开发》是一系列AIoT应用开发文章,介绍如何基于QCS6490平台做AIIoT的应用开发。 本文主要介绍FV01开发板的内部和外部接口。 内部的板载接口如下 接口…

天锐绿盾 | 设计院、机械制造行业透明加密cad图纸、图纸防泄密软件

天锐绿盾为设计院及机械制造行业量身打造的透明加密CAD图纸解决方案,专注于保障这些行业中的核心资产—设计图纸的安全。通过集成先进的加密技术和访问控制策略,该软件系统能有效防止图纸的未经授权访问和意外泄密。 PC地址: https://isite…

每日一练 2024.5.16 (补 2024.5.15)

题目: 给定一个 正整数 数组 beans ,其中每个整数表示一个袋子里装的魔法豆的数目。 请你从每个袋子中 拿出 一些豆子(也可以 不拿出),使得剩下的 非空 袋子中(即 至少还有一颗 魔法豆的袋子)…

2024汽车行业用户洞察与营销趋势白皮书

来源:小红书&寰球汽车:

设备接入物联网平台必须掌握的关键信息——青创智通

工业物联网解决方案-工业IOT-青创智通 设备接入物联网平台需要掌握的信息相当丰富且复杂,这涉及到多个层面,包括技术细节、平台选择、安全性考虑以及后期管理与维护等。以下将详细阐述设备接入物联网平台所需掌握的关键信息。 首先,我们需要…

【recast-navigation-js】通过websocket获取navmesh数据并初始化

目录 说在前面目录结构websocket服务器前端结果 说在前面 操作系统:windows 11浏览器:edge版本 124.0.2478.97recast-navigation-js版本:0.29.0golang版本:1.21.5 目录结构 D:. │ go.mod │ go.sum │ main.go // websocket …

Halcon 根据XYZ生成3D模型

Halcon 根据XYZ生成3D模型 x_points := [a_x_points, b_x_points, c_x_points]y_points := [a_y_points, b_y_points, c_y_points]z_points := [a_z_points, b_z_points, c_z_points]stop()gen_object_model_3d_from_points

风电功率预测 | 基于遗传算法优化BP神经网络实现风电功率预测(附matlab完整源码)

风电功率预测 风电功率预测 | 基于遗传算法优化BP神经网络实现风电功率预测(附matlab完整源码)完整代码风电功率预测 | 基于遗传算法优化BP神经网络实现风电功率预测(附matlab完整源码) 基于遗传算法优化BP神经网络是一种常见的方法,用于改进BP神经网络在风电功率预测中的性…

JavaScript-基本数据类型和变量

基本数据类型 JavaScript支持数字、字符串和布尔值3种基本数据类型 字符串型 字符串型是JavaScript用来表示文本的数据类型,字符串通常由单引号或双引号括起来,如果字符串存在特殊字符,可以用转义字符代替 数字型 数字型也是JavaScript中的基…