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,一经查实,立即删除!

相关文章

metasploit之ms17_010_psexec模块

‌MS17-010_psexec‌是metasploit工具的其中一个模块,‌MS17-010_psexec‌需要靶机的账号密码才能渗透(ms17_010_eternalblue是不需要靶机账密的但是我总是提示超时) 使用MS17-010_psexec‌要求: 防火墙必须允许SMB流量进出。(要…

前端配置跨域的详细指南

在现代Web开发中,跨域资源共享(CORS, Cross-Origin Resource Sharing)是一个非常重要的概念。浏览器出于安全考虑,默认情况下不允许跨域请求。如果你需要在前端与不同源的服务器进行通信,就必须配置跨域支持。本文将介…

对象克隆与单例模式

一、对象克隆 在 C 中&#xff0c;对象克隆通常可以借助拷贝构造函数和赋值运算符重载来实现&#xff0c;分为浅拷贝&#xff08;默认行为&#xff09;和深拷贝&#xff08;需要自定义实现&#xff09;。 1. 浅拷贝示例 #include <iostream> #include <string> …

Oracle virTualBox安装window10

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

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

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

三维引擎cesium学习经验

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

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

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

图片和媒体资源的优化:提升Web应用性能与用户体验的关键

文章目录 前言一、为什么需要优化图片和媒体资源二、图片优化策略三、媒体资源优化策略四、案例研究&#xff1a;实际效果展示结语 前言 在现代Web开发中&#xff0c;图片和媒体资源&#xff08;如音频、视频&#xff09;的质量和加载速度对用户体验有着直接影响。高质量的媒体…

裸机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输出电平,…

LSTM长短期记忆网络

LSTM&#xff08;长短期记忆网络&#xff09;数学原理 LSTM&#xff08;Long Short-Term Memory&#xff09;是一种特殊的递归神经网络&#xff08;RNN&#xff09;&#xff0c;解决了标准RNN中存在的梯度消失&#xff08;Vanishing Gradient&#xff09; 和**梯度爆炸&#x…

FastApi教程

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

C++进阶-1-单继承、多继承、虚继承

C单继承详解 1. 基础概念 继承是面向对象编程中的一个核心概念&#xff0c;允许一个类&#xff08;子类或派生类&#xff09;继承另一个类&#xff08;父类或基类&#xff09;的属性和方法。单继承意味着一个类只能直接继承一个父类。这种简单的结构在许多情况下是足够的&…

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

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

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

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

【AI系列】Paddle Speech安装指南

文章目录 环境依赖1. 安装Python1.1 下载Python安装包1.2 安装gcc1.3 安装依赖库1.4 编译和安装Python1.5 配置环境变量 2. 安装PaddlePaddle3. 安装PaddleSpeech4. 运行PaddleSpeech5. 解决常见问题5.1 错误&#xff1a;libssl.so.1.1解决方法&#xff1a; 5.2 错误&#xff1…

2-6-1 关于“QNX Neutrino 编程入门”的前言

阅读前言 本文以QNX系统官方的文档英文原版资料“Getting Started with QNX Neutrino: A Guide for Realtime Programmers”为参考&#xff0c;翻译和逐句校对后&#xff0c;对在QNX操作系统下进行应用程序开发及进行资源管理器编写开发等方面&#xff0c;进行了深度整理&…

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

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

StarRocks 排查单副本表

文章目录 StarRocks 排查单副本表方式1 查询元数据&#xff0c;检查分区级的副本数方式2 SHOW PARTITIONS命令查看 ReplicationNum修改副本数命令 StarRocks 排查单副本表 方式1 查询元数据&#xff0c;检查分区级的副本数 # 方式一 查询元数据&#xff0c;检查分区级的副本数…

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

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

《XML》教案 第2章 使第4章 呈现XML文档

《XML》教案 第2章 使第4章 呈现XML文档 主讲人&#xff1a; 回顾上一章: [10分钟] 2 课程知识点讲解&#xff1a; 2 通过级联样式表转换XML文档&#xff1a;[15分钟] 3 通过可扩展样式表语言转换XML文档 &#xff1a;[5分钟] 4 嵌套 for 循环 &#xff1a;[20分钟] 5 本章总结…