当前位置: 首页 > article >正文

Java中的synchronized:使用与锁升级机制

在Java并发编程中,synchronized关键字是实现线程同步的重要工具。它能够确保多个线程在访问共享资源时的线程安全性。随着Java版本的更新,synchronized的底层实现也在不断优化,尤其是引入了锁升级机制,显著提高了性能。本文将详细介绍synchronized的使用方法、底层原理以及锁升级机制。

目录

1.1 什么是synchronized?

1.2 synchronized的三种使用方式

1.2.1 修饰实例方法

1.2.2 修饰静态方法

1.2.3 修饰代码块

2. synchronized的底层原理

2.1 对象头与Monitor

2.2 Monitor的工作原理

3. 锁升级机制

3.1 锁的四种状态

3.2 锁升级的过程

3.2.1 偏向锁

3.2.2 轻量级锁

3.2.3 重量级锁

3.2.4 锁升级的流程图

4. synchronized的性能优化

4.1 减少锁的粒度

4.2 避免锁的嵌套

4.3 使用java.util.concurrent工具包

5. 示例代码

6. 总结


1.1 什么是synchronized

synchronized是Java中的关键字,用于实现线程同步。它可以修饰方法或代码块,确保同一时刻只有一个线程能够执行被修饰的代码。

1.2 synchronized的三种使用方式

1.2.1 修饰实例方法
public class Counter {private int count = 0;public synchronized void increment() {count++;}public int getCount() {return count;}
}
  • 锁对象是当前实例(this)。

  • 同一实例的多个线程会竞争同一把锁。

1.2.2 修饰静态方法
public class Counter {private static int count = 0;public static synchronized void increment() {count++;}public static int getCount() {return count;}
}
  • 锁对象是当前类的Class对象(Counter.class)。

  • 所有实例的线程都会竞争同一把锁。

1.2.3 修饰代码块
public class Counter {private int count = 0;private final Object lock = new Object();public void increment() {synchronized (lock) {count++;}}public int getCount() {return count;}
}
  • 锁对象是自定义的对象(lock)。

  • 可以更灵活地控制锁的范围。

2. synchronized的底层原理

2.1 对象头与Monitor

在JVM中,每个对象都有一个对象头,其中包含以下信息:

  • Mark Word:存储对象的哈希码、锁状态等。

  • Klass Pointer:指向对象的类元数据。

synchronized的实现依赖于对象头中的Mark Word和一个称为Monitor(监视器)的机制。每个Java对象都与一个Monitor关联,Monitor是线程同步的核心。

2.2 Monitor的工作原理

  • 当线程进入synchronized代码块时,它会尝试获取对象的Monitor

  • 如果Monitor未被占用,线程将成功获取锁并进入临界区。

  • 如果Monitor已被其他线程占用,当前线程会被阻塞,进入EntryList等待。

  • 当持有锁的线程释放锁时,会唤醒EntryList中的线程重新竞争锁。


3. 锁升级机制

在Java 6之前,synchronized的实现是完全基于重量级锁(依赖于操作系统的互斥锁),性能较差。为了优化性能,Java 6引入了锁升级机制,包括偏向锁、轻量级锁和重量级锁。

3.1 锁的四种状态

  1. 无锁状态:对象未被任何线程锁定。

  2. 偏向锁:适用于只有一个线程访问同步代码块的场景。

  3. 轻量级锁:适用于多个线程交替访问同步代码块的场景。

  4. 重量级锁:适用于多个线程竞争同一把锁的场景。

3.2 锁升级的过程

3.2.1 偏向锁
  • 适用场景:只有一个线程访问同步代码块。

  • 实现原理

    • 在对象头中记录线程ID。

    • 如果同一线程再次访问同步代码块,无需加锁,直接进入。

  • 优点:减少锁操作的开销。

3.2.2 轻量级锁
  • 适用场景:多个线程交替访问同步代码块,但没有竞争。

  • 实现原理

    • 使用CAS(Compare-And-Swap)操作尝试获取锁。

    • 如果成功,对象头中存储指向线程栈中锁记录的指针。

    • 如果失败,说明存在竞争,升级为重量级锁。

  • 优点:避免线程阻塞,减少上下文切换。

3.2.3 重量级锁
  • 适用场景:多个线程竞争同一把锁。

  • 实现原理

    • 使用操作系统的互斥锁(Mutex)实现。

    • 未获取锁的线程会被阻塞,进入EntryList等待。

  • 缺点:性能开销较大,涉及用户态和内核态的切换。

3.2.4 锁升级的流程图

无锁状态 -> 偏向锁 -> 轻量级锁 -> 重量级锁

4. synchronized的性能优化

4.1 减少锁的粒度

  • 尽量缩小同步代码块的范围,减少锁的持有时间。

  • 例如,使用细粒度锁(如ConcurrentHashMap中的分段锁)。

4.2 避免锁的嵌套

  • 锁嵌套容易导致死锁,应尽量避免。

4.3 使用java.util.concurrent工具包

  • 在高并发场景下,可以使用ReentrantLockReadWriteLock等更灵活的锁机制。


5. 示例代码

以下是一个使用synchronized的完整示例,展示了锁的竞争与释放:

public class SynchronizedDemo {private static int count = 0;private static final Object lock = new Object();public static void main(String[] args) throws InterruptedException {Runnable task = () -> {for (int i = 0; i < 1000; i++) {synchronized (lock) {count++;}}};Thread thread1 = new Thread(task);Thread thread2 = new Thread(task);thread1.start();thread2.start();thread1.join();thread2.join();System.out.println("Final count: " + count); // 输出 2000}
}

6. 总结

synchronized是Java中实现线程同步的重要工具,通过锁升级机制(偏向锁、轻量级锁、重量级锁),它在保证线程安全的同时,显著提高了性能。在实际开发中,合理使用synchronized并结合其他并发工具,可以有效提升程序的并发性能。

相关文章:

Java中的synchronized:使用与锁升级机制

在Java并发编程中&#xff0c;synchronized关键字是实现线程同步的重要工具。它能够确保多个线程在访问共享资源时的线程安全性。随着Java版本的更新&#xff0c;synchronized的底层实现也在不断优化&#xff0c;尤其是引入了锁升级机制&#xff0c;显著提高了性能。本文将详细…...

简述MySQL主从复制原理及其工作过程,配置一主两从并验证

MySQL主从复制原理:MySQL主从复制是一种常用的数据同步技术&#xff0c;它通过将一个MySQL数据库服务器&#xff08;主服务器&#xff09;的数据实时复制到一个或多个从服务器&#xff0c;从而实现数据的备份、读写分离以及高可用性等目标. 基于binlog的主从同步 #主服务器配…...

MySQL8.0 innodb Cluster 高可用集群部署(MySQL、MySQL Shell、MySQL Router安装)

简介 MySQL InnoDB集群&#xff08;Cluster&#xff09;提供了一个集成的&#xff0c;本地的&#xff0c;HA解决方案。Mysq Innodb Cluster是利用组复制的 pxos 协议&#xff0c;保障数据一致性&#xff0c;组复制支持单主模式和多主模式。 InnoDB Cluster组件&#xff1a; …...

【时时三省】(C语言基础)简单的算法举例

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 判定2000—2500年中的每一年是否为闰年&#xff0c;并将结果输出。 本先分析闰年的条件&#xff1a; &#xff08;1&#xff09;能被4整除&#xff0c;但不能被100整除的年份都是闰年&…...

走进 Tcl 语言:历史、特性与应用

亲爱的小伙伴们&#x1f618;&#xff0c;在求知的漫漫旅途中&#xff0c;若你对深度学习的奥秘、Java 与 Python 的奇妙世界&#xff0c;亦或是读研论文的撰写攻略有所探寻&#x1f9d0;&#xff0c;那不妨给我一个小小的关注吧&#x1f970;。我会精心筹备&#xff0c;在未来…...

Day42(补)【AI思考】-编译过程中语法分析及递归子程序分析法的系统性解析

文章目录 编译过程中语法分析及递归子程序分析法的系统性解析**一、总览&#xff1a;编译流程中的语法分析****1. 编译过程核心步骤** **二、语法分析的核心任务****1. 核心目标****2. 现实类比** **三、递归子程序分析法的本质****1. 方法分类****2. 递归子程序分析法的运作原…...

Effective Objective-C 2.0 读书笔记——内存管理(上)

Effective Objective-C 2.0 读书笔记——内存管理&#xff08;上&#xff09; 文章目录 Effective Objective-C 2.0 读书笔记——内存管理&#xff08;上&#xff09;引用计数属性存取方法中的内存管理autorelease保留环 ARCARC必须遵循的方法命名原则ARC 的自动优化&#xff1…...

软件测试覆盖率详解

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、覆盖率概念 覆盖率是用来度量测试完整性的一个手段&#xff0c;是测试技术有效性的一个度量。分为&#xff1a;白盒覆盖、灰盒覆盖和黑盒覆盖&#xff1b;测…...

控制玉米株高基因 PHR1 的基因克隆

https://zwxb.chinacrops.org/CN/10.3724/SP.J.1006.2024.33011...

windows10本地的JMeter+Influxdb+Grafana压测性能测试,【亲测,避坑】

一、环境&#xff0c;以下软件需要解压、安装到电脑上。 windows10 apache-jmeter-5.6.3 jdk-17.0.13 influxdb2-2.7.11 grafana-enterprise-11.5.1二、配置Influxdb&#xff0c;安装完默认连接http://localhost:8086/。打开连接&#xff0c;配置如下。 开启Influxdb&#xf…...

那些数据库函数那些事儿

stdio 1.基本概念 文件: 一组相关数据的集合 文件名: 01.sh //文件名 2.linux下的文件类型 b block 块设备文件 eg: 硬盘 c character 字符设备文件 eg: 鼠标&#xff0c;键盘 d directory 目录文件 eg: 文件夹 - regular 常…...

Excel中不用复杂公式根据指定X列的数值N复制整行数据N行简单方法

Excel中不用复杂公式根据指定X列的数值N复制整行数据N行简单方法 1、在“数据表”sheet1中对指定X列&#xff08;假设X列的数字从X2开始到Xn结束&#xff09;求和&#xff0c;和为Y。 2、在“数据表”sheet1数据列之外新建一列Z&#xff0c;Z1输入表头“匹配数据列”&#xff…...

如何在 Java 后端接口中提取请求头中的 Cookie 和 Token

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务) &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1;个人微信&a…...

【Python网络爬虫】爬取网站图片实战

【Python网络爬虫】爬取网站图片实战 Scrapying Images on Website in Action By Jackson@ML *声明:本文简要介绍如何利用Python爬取网站数据图片,仅供学习交流。如涉及敏感图片或者违禁事项,请注意规避;笔者不承担相关责任。 1. 创建Python项目 1) 获取和安装最新版…...

SAP ABAP VA05增强

SE18 输入增强的BADI名称:BADI_SDOC_WRAPPER 进入后,点击Interface。 进入后,点击显示对象清单。 双击增强类,下面有之前做好的增强类,没有的可以自己创建一个。 IF_BADI_SDOC_WRAPPER~ADAPT_RESULT_COMP 代码 METHOD if_badi_sdoc_wrapper~adapt_result_comp."…...

八大排序——简单选择排序

目录 1.1基本操作&#xff1a; 1.2动态图&#xff1a; 1.3代码&#xff1a; 代码解释 1. main 方法 2. selectSort 方法 示例运行过程 初始数组 每轮排序后的数组 最终排序结果 代码总结 1.1基本操作&#xff1a; 选择排序&#xff08;select sorting&#xff09;也…...

【清晰教程】本地部署DeepSeek-r1模型

【清晰教程】通过Docker为本地DeepSeek-r1部署WebUI界面-CSDN博客 目录 Ollama 安装Ollama DeepSeek-r1模型 安装DeepSeek-r1模型 Ollama Ollama 是一个开源工具&#xff0c;专注于简化大型语言模型&#xff08;LLMs&#xff09;的本地部署和管理。它允许用户在本地计算机…...

教程 | Proxmox VE(PVE)安装全流程指南(末尾附镜像及快速配置脚本)

Proxmox VE 是一款基于 Debian 的开源虚拟化平台&#xff0c;支持 KVM 虚拟机和 LXC 容器&#xff0c;广泛用于企业级虚拟化部署。 一、安装前准备 1. 硬件要求 CPU&#xff1a;64位处理器&#xff08;Intel VT/AMD-V 虚拟化支持&#xff09;内存&#xff1a;至少 4GB&#x…...

【matlab优化算法-17期】基于DBO算法的微电网多目标优化调度

基于蜣螂DBO算法的微电网多目标优化调度 一、前言 微电网作为智能电网的重要组成部分&#xff0c;其优化调度对于降低能耗、减少环境污染具有重要意义。本文介绍了一个基于Dung Beetle Optimizer&#xff08;DBO&#xff09;算法的微电网多目标优化调度项目&#xff0c;旨在通…...

如何使用qt开发一个xml发票浏览器,实现按发票样式显示

使用Qt开发一个按发票样式显示的XML发票浏览器&#xff0c;如下图所示样式&#xff1a; 一、需求&#xff1a; 1、按税务发票样式显示。 2、拖入即可显示。 3、正确解析xml文件。 二、实现 可以按照以下步骤进行&#xff1a; 1. 创建Qt项目 打开Qt Creator&#xff0c;创…...

八股文-2025-02-12

BFC BFC属于普通流。BFC全称是Block Formatting Context&#xff0c;意思就是块级格式化上下文。你可以把BFC看做元素的一个属性&#xff0c;当元素拥有BFC属性&#xff0c;这个元素就可以看作是隔离了的独立容器&#xff0c;容器里边的元素不会影响到容器外部的元素.https://b…...

解析 JavaScript 面试题:`index | 0` 确保数组索引为整数

文章目录 一、JavaScript 中的数字类型二、按位或运算符 | 的作用&#xff08;一&#xff09;对于整数&#xff08;二&#xff09;对于小数&#xff08;三&#xff09;对于非数字值 三、用于数组索引的意义 在 JavaScript 面试中&#xff0c;常常会涉及到一些看似简单却蕴含着深…...

苹果手机快捷指令----敲击背面实现自动插入日期

前一段时间因为写文章&#xff0c;每一次总是在手机上面敲击日期觉得非常麻烦&#xff0c;于是自己鼓捣如何自动插入的办法。下面分享在网络上面查阅到的资料&#xff0c;由于实操的原因&#xff0c;遇到了很多困难。现在补充上去。先演示一遍效果。 https://www.bilibili.com…...

Base64 PDF解析器

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Base64 PDF解析器</title><style>body {font-family: Arial, sans-serif;max-width: 800px;margin: 20px auto;padding: 20px;}.contain…...

SQL-leetcode—1393. 股票的资本损益

1393. 股票的资本损益 Stocks 表&#xff1a; ---------------------- | Column Name | Type | ---------------------- | stock_name | varchar | | operation | enum | | operation_day | int | | price | int | ---------------------- (stock_name, operation_day) 是这张…...

Java NIO基础与实战:如何提升IO操作性能

Java NIO 概述 Java NIO&#xff08;新 I/O&#xff09;是 Java 提供的一个更为高效的 I/O 处理框架。Java NIO&#xff08;New I/O&#xff09;是对传统 I/O&#xff08;java.io&#xff09;模型的改进&#xff0c;它引入了非阻塞 I/O 操作和面向缓冲区的数据读写方式&#x…...

46 map与set

目录 一、序列式容器和关联式容器 二、set系列的使用 &#xff08;一&#xff09;set和mutilset参考文档链接 &#xff08;二&#xff09;set类模板介绍 1、set类声明 2、set的构造和迭代器 3、set的增删查 &#xff08;三&#xff09;multiset类模板 1、multiset和se…...

GPT 系列模型发展史:从 GPT 到 ChatGPT 的演进与技术细节

从 GPT 到 ChatGPT&#xff0c;OpenAI 用短短几年时间&#xff0c;彻底改变了自然语言处理&#xff08;NLP&#xff09;的格局。让我们一起回顾这段激动人心的技术演进史&#xff01;&#x1f680; &#x1f539; GPT&#xff08;2018&#xff09;&#xff1a; 划时代的起点&a…...

RAGFlow和Dify对比

‌ RAGFlow和Dify都是基于大语言模型&#xff08;LLM&#xff09;的应用开发平台&#xff0c;具有相似的功能和应用场景&#xff0c;但它们在技术架构、部署要求和用户体验上存在一些差异。‌‌ RAGFlow和Dify对比 2025-02-13 22.08 RAGFlow‌ ‌技术栈‌&#xff1a;RAGFlow…...

Dart 3.5语法 14-16

017自定代码段让变量有默认值 List下标访问和2种for循环遍历_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1RZ421p7BL?spm_id_from333.788.videopod.episodes&vd_source68aea1c1d33b45ca3285a52d4ef7365f&p42原作者链接&#xff0c;此为修订补充版本 014main…...