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

线程同步相关知识

文章目录

      • 一、线程同步的核心目标
      • 二、线程安全的判定条件
      • 三、同步方式一:synchronized 关键字
        • 1. 同步代码块
        • 2. 同步方法
      • 四、锁的释放与不释放场景
        • 1. 自动释放锁的场景
        • 2. 不会释放锁的场景
      • 五、同步方式二:ReentrantLock(显式锁)
        • 1. 核心特性
        • 2. 使用规范
      • 六、synchronized 与 ReentrantLock 的对比
      • 总结

以下是对线程同步相关知识点的系统整理,涵盖同步方式、锁机制、线程安全条件及释放规则等核心内容:

一、线程同步的核心目标

解决多线程并发操作共享资源时的线程安全问题(如数据不一致、重复修改等),通过控制线程对共享资源的访问顺序,保证操作的原子性、可见性和有序性。

二、线程安全的判定条件

出现线程安全问题必须同时满足两个条件:

  1. 多线程环境:程序运行在多个线程并发执行的场景中。
  2. 共享资源:多个线程操作的是同一份资源(如共享变量、对象属性等)。

解决方案:通过“锁机制”保证同一时间只有一个线程能操作共享资源,核心是所有线程必须使用同一把锁

三、同步方式一:synchronized 关键字

synchronized 是 Java 内置的隐式锁机制,通过“监视器(Monitor)”实现,可修饰代码块或方法。

1. 同步代码块
  • 语法

    synchronized (锁对象) {// 需要同步的代码(操作共享资源的逻辑)
    }
    
  • 核心要素

    • 锁对象:可以是任意对象(通常使用共享资源本身或 this),但必须保证所有线程使用同一把锁
    • 同步范围:仅包含操作共享资源的代码,范围越小,效率越高。
  • 示例

    // 共享资源
    private int count = 0;
    private Object lock = new Object(); // 锁对象// 多线程执行的方法
    public void increment() {synchronized (lock) { // 所有线程使用同一把lock锁count++; // 操作共享资源}
    }
    
2. 同步方法
  • 语法:直接在方法声明处添加 synchronized 关键字,隐式指定锁对象。

    // 实例方法
    public synchronized void method1() { ... }// 静态方法
    public static synchronized void method2() { ... }
    
  • 隐式锁对象规则

    • 实例方法:锁对象为 this(当前对象实例)。
    • 静态方法:锁对象为 类名.class(当前类的字节码对象,全局唯一)。
  • 特点

    • 无需显式指定锁对象,简化代码,但同步范围是整个方法(可能降低效率)。
    • 静态同步方法和实例同步方法使用的是不同锁(类对象 vs 实例对象),两者不会互斥。

四、锁的释放与不释放场景

synchronized 锁的释放由 JVM 自动管理,以下情况会触发释放或不释放:

1. 自动释放锁的场景
  • 同步代码块或同步方法正常执行完毕(执行到代码块末尾)。
  • 同步代码中出现未捕获的异常或错误,导致线程终止。
  • 同步代码中调用 wait() 方法(线程进入等待状态,主动释放锁)。
  • 同步代码中通过 breakreturn 等语句退出代码块/方法。
2. 不会释放锁的场景
  • 调用 Thread.sleep(long):线程休眠时仍持有锁(其他线程无法获取)。
  • 调用 Thread.yield():线程主动让出 CPU,但锁未释放。
  • 线程被 suspend() 暂停(已过时方法):暂停期间仍持有锁,可能导致死锁。

五、同步方式二:ReentrantLock(显式锁)

java.util.concurrent.locks.ReentrantLock 是 JDK 提供的显式锁实现,比 synchronized 更灵活。

1. 核心特性
  • 可重入性:同一线程可多次获取同一把锁(与 synchronized 一致)。
  • 公平性:通过构造函数指定是否为公平锁:
    ReentrantLock fairLock = new ReentrantLock(true); // 公平锁(按请求顺序获取锁)
    ReentrantLock nonfairLock = new ReentrantLock(false); // 非公平锁(默认,可能插队)
    
    • 公平锁:线程按请求锁的顺序获取锁,避免饥饿,但效率较低。
    • 非公平锁:允许线程“插队”获取锁,效率更高,但可能导致部分线程长期等待。
2. 使用规范

必须手动获取锁和释放锁,且释放操作需放在 finally 中,确保锁一定被释放:

ReentrantLock lock = new ReentrantLock();public void operation() {lock.lock(); // 手动获取锁try {// 操作共享资源(可能出现线程安全的代码)} finally {lock.unlock(); // 手动释放锁,必须在finally中}
}

六、synchronized 与 ReentrantLock 的对比

特性synchronizedReentrantLock
锁类型隐式锁(JVM 自动管理)显式锁(手动获取和释放)
公平性仅支持非公平锁可通过构造函数指定公平/非公平
可中断性不可中断支持中断(lockInterruptibly()
条件变量仅支持 wait()/notify()支持多个 Condition 对象,更灵活
性能JDK 1.6 后优化,与 ReentrantLock 接近高并发下略优,功能更丰富

总结

  1. 线程同步的核心是通过锁机制控制共享资源的并发访问,需保证多线程使用同一把锁。
  2. synchronized 适合简单场景,隐式管理锁的获取和释放,易用性高。
  3. ReentrantLock 适合复杂场景(如公平性控制、中断处理),需手动管理锁,灵活性更高。
  4. 无论使用哪种锁,都需注意锁的释放时机,避免死锁(如 sleep() 不释放锁可能导致的问题)。

合理选择同步方式是保证多线程程序正确性和效率的关键。

http://www.lryc.cn/news/614754.html

相关文章:

  • 构建高可用架构:ZDNS GSLB 在多数据中心场景下的应用与 F5 替换实践
  • Linux网络--1、网络基础
  • Java零散知识点
  • Claude Code:智能代码审查工具实战案例分享
  • 阶段二测试
  • 华为网路设备学习-28(BGP协议 三)路由策略
  • Latex中公式部分输入正体的字母\mathrm{c}
  • v-model双向绑定指令
  • 【工作笔记】Docker Desktop一直转圈加载不出来然后报错
  • 数据结构---二叉树(概念、特点、分类、特性、读取顺序、例题)、gdb调试指令、时间复杂度(概念、大O符号法、分类)
  • CSS:BFC
  • 深入解析Linux信号处理机制
  • DeepSeek辅助编写的带缓存检查的数据库查询缓存系统
  • 三方相机问题分析七:【datespace导致GPU异常】三方黑块和花图问题
  • Sum of Three Values(sorting and searching)
  • 基于MATLAB实现的毫米波大规模MIMO系统中继混合预编码设计
  • Python Day26 HTTP 协议相关笔记
  • Neo4j APOC插件安装教程
  • 论文阅读:AAAI 2024 ExpeL: LLM Agents Are Experiential Learners
  • 连锁店管理系统的库存跟踪功能:数字化转型下的零售运营核心
  • Nextcloud容器化部署新范式:Docker与Cpolar如何重塑私有云远程访问能力
  • 浅试A2A
  • 商品 SKU 计算,库存不足不能选择
  • SpringBoot的profile加载
  • C++ 模拟实现 map 和 set:掌握核心数据结构
  • 恒科持续低迷:新能源汽车股下跌成拖累,销量担忧加剧
  • Mac下安装Conda虚拟环境管理器
  • AI开发平台行业全景分析与战略方向建议
  • WPF 动画卡顿
  • Seaborn 数据可视化库:入门与进阶指南