Java中的锁机制 与 synchronized的理解

** Java中的锁机制**

1. 公平锁 vs 非公平锁
  • 公平锁:公平锁的特点是多个线程按照请求锁的顺序来获取锁,即遵循 FIFO(先进先出)顺序。公平锁会避免“饥饿”现象,即后申请锁的线程不会比先申请的线程更早获取锁。Java中的 ReentrantLock 可以通过构造函数指定是否公平锁。如果传入 true,则创建公平锁。

  • 非公平锁:非公平锁则没有严格按照顺序分配锁,后申请的线程有可能比先申请的线程更早获得锁。这种锁的好处是性能较高,因为它减少了等待时间,避免了严格排队的开销。ReentrantLock 的默认锁是非公平的。synchronized 也属于非公平锁。

举例

  • 公平锁:假设有三个线程 T1T2T3,当 T1 获取锁后,T2 会等待,直到 T1 释放锁,T2 才能获得锁。当 T2 释放锁时,T3 会按顺序获取锁。
  • 非公平锁:假设有三个线程 T1T2T3,即使 T1 先申请了锁,T2 可能会因为某些条件(如线程调度)先获取到锁,导致 T1 等待。
2. 可重入锁(递归锁)

可重入锁的意思是同一个线程可以多次获取同一把锁,而不会发生死锁。一个线程获取锁后,可以进入该锁保护的代码块,即使它已经持有锁,也能继续获得该锁。这使得代码在调用嵌套方法时不会被阻塞。

举例

  • ReentrantLocksynchronized 都是可重入锁。比如,在一个方法中获取锁后,再调用另一个方法,若该方法也需要相同的锁,线程仍然可以继续执行。

代码示例

class ReentrantLockExample {private final ReentrantLock lock = new ReentrantLock();public void outerMethod() {lock.lock();try {System.out.println("Outer method");innerMethod(); // 内部方法依然能获取锁} finally {lock.unlock();}}public void innerMethod() {lock.lock();try {System.out.println("Inner method");} finally {lock.unlock();}}
}

在这个例子中,outerMethodinnerMethod 都需要 lock,但线程能够成功执行,因为 ReentrantLock 允许同一线程获取同一个锁。

3. 独享锁 vs 共享锁
  • 独享锁:独享锁是指同一时间只有一个线程可以持有锁。ReentrantLock 就是独享锁的实现。比如,synchronized 也是独享锁。

  • 共享锁:共享锁允许多个线程同时持有锁。ReadWriteLock 中的读锁就是共享锁,多个线程可以同时获取读锁,而写锁是独享锁,只能有一个线程持有。

举例

  • 独享锁:一个线程获取锁后,其他线程必须等待锁被释放,直到锁的持有者释放锁。
  • 共享锁:多个线程可以同时读取数据,只要没有线程进行写操作(获取写锁)。
4. 互斥锁 vs 读写锁
  • 互斥锁:互斥锁是指一次只能有一个线程持有锁。例如 ReentrantLock 就是互斥锁,它保证每次只有一个线程可以执行临界区代码。

  • 读写锁:读写锁是一种特殊的锁,它分为读锁和写锁。多个线程可以同时持有读锁,但写锁是独占的。ReadWriteLock 提供了读写锁机制,适用于读操作远远多于写操作的场景,可以提高并发性能。

举例

  • 互斥锁:比如多个线程同时访问一个共享资源,但只有一个线程能够获取锁并执行。
  • 读写锁:当多个线程同时读取数据时,可以同时获取读锁,但如果有一个线程尝试写数据,则所有的读线程都需要释放读锁,写线程才能获取写锁。
5. 乐观锁 vs 悲观锁
  • 悲观锁:悲观锁认为并发操作一定会导致冲突,因此它总是加锁,确保数据安全。synchronizedReentrantLock 都属于悲观锁。

  • 乐观锁:乐观锁认为并发操作不会冲突,因此它不会加锁,而是在执行操作时进行检查,如果数据没有被修改,则更新;如果被修改了,则重新尝试。常见的实现方式是 CAS(Compare-And-Swap),Java 中的原子类(如 AtomicInteger)就是使用 CAS 来实现的。

举例

  • 悲观锁:在多线程操作共享资源时,所有线程都需要获取锁来确保安全,保证数据一致性。
  • 乐观锁:线程不加锁,直接执行操作,如果发现数据被修改则重新执行操作,而不是等待锁释放。
6. 分段锁

分段锁是将锁分为多个段,每个段可以独立地加锁,从而提高并发性能。ConcurrentHashMap 就是通过分段锁来实现高效的并发操作,每个段内独立加锁,这样多个线程可以同时操作不同的段。

举例

  • 假设 ConcurrentHashMap 中有 16 个段,每个段都可以独立加锁,这样多个线程可以并发地访问不同的段,提高了并发性。
7. 偏向锁、轻量级锁、重量级锁

这些锁是针对 synchronized 的优化,JVM 会根据线程的竞争情况进行锁的升级:

  • 偏向锁:如果一个线程频繁访问同步代码块,它会获得偏向锁,这样可以减少锁竞争的开销。
  • 轻量级锁:当偏向锁被其他线程竞争时,JVM 会将偏向锁升级为轻量级锁。此时,其他线程尝试通过自旋获取锁。
  • 重量级锁:当自旋锁竞争激烈时,锁会升级为重量级锁,其他线程会被阻塞,性能会下降。

synchronized的理解

Synchronized 是 Java 中用于实现同步的一种机制。它确保同一时刻只有一个线程能够访问被修饰的代码块或方法,防止多个线程同时访问共享资源导致数据不一致。

1. 工作原理

当一个线程执行某个被 synchronized 修饰的方法或代码块时,它会获取到锁(称为对象锁或类锁)。其他线程在访问该方法或代码块时,如果没有获得锁,则会被阻塞,直到当前线程释放锁。

  • 修饰实例方法:锁住的是实例对象(this)。
  • 修饰静态方法:锁住的是类的 Class 对象。
  • 修饰代码块:锁住的是指定对象。
2. 锁的种类
  • 方法锁:当 synchronized 修饰方法时,整个方法都会被锁住。
  • 代码块锁:当 synchronized 修饰代码块时,只有代码块内的部分被锁住。
3. 性能优化

从 Java 5 开始,JVM 对 synchronized 进行了优化,引入了偏向锁、轻量级锁、重量级锁等机制。锁的升级有助于减少不必要的锁竞争,从而提高性能。

4. 死锁的风险

Synchronized 锁可能导致死锁,特别是在多个线程相互等待对方释放锁时。例如:

class A {synchronized void method1(B b) {b.last();}synchronized void last() {}
}class B {synchronized void method2(A a) {a.last();}synchronized void last() {}
}

如果线程 T1 在 A.method1() 中持有 A 锁,且需要 B 锁,线程 T2 在 B.method2() 中持有 B 锁,且需要 A 锁,那么就会发生死锁。


总结

  • Synchronized 是用于线程同步的关键字,保证在同一时刻只有一个线程能够访问临界区代码。
  • 锁机制有不同种类,适用于不同的场景,如 公平锁/非公平锁可重入锁悲观锁/乐观锁 等。

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

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

相关文章

Oracle virTualBox安装window10

一、下载windows10镜像 我下载的windows10镜像如下: 内部文件如下: 二、错误的安装方法 直接新建虚拟机,选择镜像文件: 启动虚拟机(会一直提示没有启动设备,选择镜像后一直弹窗提示) 三、正确…

四川托普信息技术职业学院教案1

四川托普信息技术职业学院教案 【计科系】 周次 第 1周,第1次课 备 注 章节名称 第1章 XML语言简介 引言 1.1 HTML与标记语言 1.2 XML的来源 1.3 XML的制定目标 1.4 XML概述 1.5 有了HTML了,为什么还要发展XML 1.5.1 HTML的缺点 1.5.2 XML的特点 1.6 X…

三维引擎cesium学习经验

三维引擎cesium学习经验: 1、初始化viewer对象 2、对entity的操作:添加,隐藏,修改,去除,居中显示 3、去除掉entity的双击事件 4、获取当前视角高度 5、获取经纬度在屏幕上的位置 6、获取三维场景屏幕中心点…

虚拟机VMware的安装问题ip错误,虚拟网卡

要么没有虚拟网卡、有网卡远程连不上等 一般出现在win11 家庭版 1、是否IP错误 ip addr 2、 重置虚拟网卡 3、查看是否有虚拟网卡 4、如果以上检查都解决不了问题 如果你之前有vmware 后来卸载了,又重新安装,一般都会有问题 卸载重装vmware: 第一…

裸机LED 灯实验

G1、硬件原理分析 2、寄存器说明 a、主要配置寄存器 使能 GPIO1 时钟—CCM_CCGR1 设置 GPIO1_IO03 的复用功能—IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 配置 GPIO1_IO03—IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 设置GPIO GPIO1_GDIR 的 bit3 要设置为 1,表示输出 控制GPIO输出电平,…

FastApi教程

FastApi,一个用于构建 API 的现代、快速(高性能)的web框架。 FastApi是建立在Starlette和Pydantic基础上的,Pydantic是一个基于Python类型提示来定义数据验证、序列化和文档的库。Starlette是一种轻量级的ASGI框架/工具包&#x…

C语言 文件操作——按行读写文件

目录 按行写文件 按行读文件 按行读写文件 按行写文件 int puts ( const char *s ); 将字符串 s 写入标准输出流 stdout ,并在其后添加一个换行符 按字符串(行) 写 文件 int fputs ( const char *s, FILE *fp); 将字符串 s 写入 fp 所…

轻松上手:使用 Vercel 部署 HTML 页面教程

😀 在学习前端的过程中,部署项目往往是一个令人头疼的问题。然而,Vercel 为我们提供了一个便捷且免费的解决方案。 Vercel 是一个强大的云平台,专门用于前端项目的部署和托管。它不仅支持多种前端框架和静态网站生成器&#xff0…

【中标麒麟服务器操作系统实例分享】java应用DNS解析异常分析及处理

了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://documentkylinos.cn 情况描述 中标麒麟服务器操作系统V7运行在 ARM虚…

基于Transformer的自编码器模型在故障检测中的应用

在现代工业和制造领域,故障检测是保证设备和生产线安全、高效运行的关键。传统的故障检测方法往往依赖于人工经验或规则,然而,这些方法的准确性和泛化能力有限。随着深度学习技术的迅速发展,越来越多的智能故障检测方法应运而生&a…

Sigrity System Explorer Snip Via Pattern From Layout模式从其它设计中截取过孔模型和仿真分析操作指导

Sigrity System Explorer Snip Via Pattern From Layout模式从其它设计中截取过孔模型和仿真分析操作指导 Sigrity System Explorer Snip Via Pattern From Layout模式支持从其它设计中截取过孔模型用于仿真分析,同样以差分模板为例 具体操作如下 双击打开System Explorer软件…

2024年度个人总结

一转眼已经2024年度最后一个月了,今年基本没有在CSDN发布内容,包括其他平台(B站),倒是在其他地方(我的个人网站和V2EX)发布一些零碎的东西,主要是因为今年换了工作后太累了&#xff…

汽车IVI中控开发入门及进阶(42):OpenVG

概览: OpenVG是一个无版权、跨平台的API,它为高级用户界面和矢量图形库(如SVG)提供了一个低级硬件加速接口。OpenVG主要针对需要便携式加速高质量矢量图形以获得引人注目的用户界面和文本的消费电子产品、手持设备、可穿戴设备和汽车设备,同时使硬件加速能够在非常低的功…

基于微信小程序的消防隐患在线举报系统

博主介绍:java高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了多年的设计程序开发,开发过上千套设计程序,没有什么华丽的语言,只有实…

如何重新设置VSCode的密钥环密码?

故障现象: 忘记了Vscode的这个密码: Enter password to unlock An application wants access to the keyring “Default ke... Password: The unlock password was incorrect Cancel Unlock 解决办法: 1.任意terminal下,输入如下…

springcloud-gateway获取应用响应信息乱码

客户端通过springcloud gateway跳转访问tongweb上的应用,接口响应信息乱码。使用postman直接访问tongweb上的应用,响应信息显示正常。 用户gateway中自定义了实现GlobalFilter的Filter类,在该类中获取了上游应用接口的响应信息,直…

JS萤石云录像回放拖动进度条无法正常播放

问题描述: 本项目版本:vue2.6.12,webpack3.6.0,ezuikit-js0.7.2 在使用萤石云的JavaScript SDK做监控的直播、录像回放时,遇到部分设备的录像回放,无法根据控制面板的拖动进度条查看某时间段的录像。 官方…

2024.12.21辩论赛感受

背景 今天辩论赛的双方论点是: 正方:寒假留在研发中心的收获大 反方:寒假去做其他事情的收获 辩论赛,为了锻炼自己,选择了不想选择以及相对不好辩论的反方。出现的状况有一下几点: 1.发现自己脑子完全跟不…

混元大模型简介及个人运行方案

一、混元大模型简介 混元大模型(HunyuanVideo)是一个开源的视频生成基础模型,专为高质量的视频生成任务设计。它融合了多项先进技术和创新架构,在视觉质量、多样性、文本与视频的对齐度,以及生成的稳定性方面表现出色…

图漾相机-ROS1_SDK_ubuntu版本编译(新版本)

文章目录 官网编译文档链接官网SDK下载链接1、下载 Camport ROS1 SDK1.下载git2、下载链接 2、准备编译工作1、安装 catkin2、配置环境变量3. 将Camport3中的linux库文件拷贝到 user/lib目录下4、修改lunch文件制定相机(可以放在最后可以参考在线文档)**…