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

Synchronized锁的使用方式

文章目录

      • 一、修饰实例方法(对象锁)
        • 示例:
        • 特点:
      • 二、修饰静态方法(类锁)
        • 示例:
        • 特点:
      • 三、修饰代码块(对象锁/类锁)
        • 1. 锁对象为实例对象(`this`)
        • 2. 锁对象为类对象(`XXX.class`)
        • 3. 锁对象为自定义对象(推荐)
        • 特点:
      • 四、使用注意事项
      • 总结

在Java中,synchronized是一种内置锁机制,用于实现多线程间的同步,保证临界区代码的原子性和可见性。其使用方式主要有以下四种,适用于不同的同步场景:

一、修饰实例方法(对象锁)

synchronized修饰实例方法时,锁的对象是当前类的实例对象(this。多个线程访问同一个实例的同步方法时,会竞争该实例的锁,同一时间只有一个线程能执行。

示例:
public class SyncDemo {// 同步实例方法,锁为当前对象(this)public synchronized void instanceMethod() {// 临界区代码(如操作共享资源)System.out.println(Thread.currentThread().getName() + "执行同步方法");try {Thread.sleep(1000); // 模拟耗时操作} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String[] args) {SyncDemo demo = new SyncDemo();// 两个线程访问同一个实例的同步方法,会串行执行new Thread(demo::instanceMethod, "线程1").start();new Thread(demo::instanceMethod, "线程2").start();}
}
特点:
  • 锁的是对象实例,不同实例间的同步方法互不干扰(如new SyncDemo()new SyncDemo()的同步方法可并行执行)。
  • 同一实例的多个同步方法共享同一把锁(一个线程执行methodA()时,其他线程无法执行该实例的methodB())。

二、修饰静态方法(类锁)

synchronized修饰静态方法时,锁的对象是当前类的Class对象(每个类只有一个Class对象)。多个线程访问该类的任何静态同步方法时,都会竞争这把类锁。

示例:
public class SyncDemo {// 同步静态方法,锁为当前类的Class对象(SyncDemo.class)public static synchronized void staticMethod() {System.out.println(Thread.currentThread().getName() + "执行静态同步方法");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}public static void main(String[] args) {// 两个线程访问静态同步方法,无论是否同一实例,都会串行执行new Thread(SyncDemo::staticMethod, "线程1").start();new Thread(SyncDemo::staticMethod, "线程2").start();}
}
特点:
  • 锁的是类对象,所有实例共享这把锁(即使new SyncDemo()多个实例,静态同步方法仍串行执行)。
  • 静态同步方法与实例同步方法使用不同的锁(互不干扰,可并行执行)。

三、修饰代码块(对象锁/类锁)

synchronized代码块可以指定自定义锁对象,只对该代码块加锁,粒度更细,灵活性更高。根据锁对象的类型,可分为:

1. 锁对象为实例对象(this

与同步实例方法的锁一致,控制同一实例对代码块的并发访问。

public class SyncDemo {public void method() {// 同步代码块,锁为当前对象(this)synchronized (this) {System.out.println(Thread.currentThread().getName() + "执行同步代码块");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
2. 锁对象为类对象(XXX.class

与同步静态方法的锁一致,控制所有实例对代码块的并发访问。

public class SyncDemo {public void method() {// 同步代码块,锁为类对象(SyncDemo.class)synchronized (SyncDemo.class) {System.out.println(Thread.currentThread().getName() + "执行同步代码块");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
3. 锁对象为自定义对象(推荐)

使用专门的锁对象(如Object实例),避免与其他同步方法/代码块共享锁,减少锁竞争。

public class SyncDemo {// 自定义锁对象(推荐使用private final修饰,避免被修改)private final Object lock = new Object();public void method() {// 同步代码块,锁为自定义对象locksynchronized (lock) {// 临界区代码}}
}
特点:
  • 粒度更细:仅对需要同步的代码块加锁,其他代码可并行执行,性能更高。
  • 灵活可控:可通过不同的锁对象实现多组独立同步(如lock1控制A代码块,lock2控制B代码块,互不干扰)。

四、使用注意事项

  1. 锁的可重入性
    synchronized是可重入锁,同一线程可多次获取同一把锁(如同步方法中调用同一对象的其他同步方法,不会死锁)。

  2. 锁的释放
    线程执行完同步代码(正常退出或抛出异常)后,会自动释放锁,无需手动操作。

  3. 避免锁竞争过度

  • 同步范围不宜过大(如只锁必要的代码块,而非整个方法),减少线程阻塞时间。
  • 避免使用String常量或Integer等包装类作为锁对象(可能因常量池导致锁共享)。
  1. wait()/notify()配合
    在同步代码块中,可通过锁对象.wait()让线程等待,锁对象.notify()唤醒线程,实现线程协作(如生产者-消费者模型)。

总结

synchronized的三种使用方式各有适用场景:

  • 实例方法:控制同一实例的方法级同步,简单直接。
  • 静态方法:控制类级别的同步,适用于静态资源的并发访问。
  • 代码块:粒度更细,可自定义锁对象,灵活性最高,推荐优先使用。

合理选择使用方式,可在保证线程安全的同时,减少性能损耗。

http://www.dtcms.com/a/330081.html

相关文章:

  • three.js学习记录(鼠标控制)
  • Linux 计划任务
  • 【web站点安全开发】任务3:网页开发的骨架HTML与美容术CSS
  • STM32学习笔记10—DMA
  • JSON索引香港VPS:高效数据处理的完美解决方案
  • JDK17下载与安装图文教程(保姆级教程)
  • 《汇编语言:基于X86处理器》第13章 复习题和编程练习
  • VerIF
  • 【R语言】RStudio 中的 Source on Save、Run、Source 辨析
  • [系统架构设计师]系统架构基础知识(一)
  • MySQL表约束
  • 关于大学计算机专业的课程的一些看法
  • windows通过共享网络上网
  • JavaWeb之响应
  • 使用BeautifulReport让自动化测试报告一键生成
  • 开源组件的“暗礁”:第三方库中的输入与边界风险治理
  • 「数据获取」《广西调查年鉴》(2007-2024)(2009缺失)(获取方式看绑定的资源)
  • GISBox工具处理:将高斯泼溅模型导出为3DTiles
  • 【15】Transformers快速入门:添加自定义 Token
  • 服务器安全防护
  • ARM芯片架构之CoreSight Channel Interface 介绍
  • 基于边缘深度学习的棒球击球训练评估研究
  • 模型训练不再“卡脖子”:国产AI训练平台对比与落地实践指南
  • 马力是多少W,常见车辆的马力范围
  • RK3568项目(十四)--linux驱动开发之常用外设
  • 中科米堆CASAIM蓝光三维扫描仪用于焊接件3D尺寸检测
  • 2025 开源语音合成模型全景解析:从工业级性能到创新架构的技术图谱
  • Python实现点云概率ICP(GICP)配准——精配准
  • static 和 extern 关键字
  • 公用表表达式和表变量的用法区别?