springboot synchronized 本地锁入门与实战

发布于:2025-09-12 ⋅ 阅读:(17) ⋅ 点赞:(0)

Spring Boot3 Synchronized 项目地址

https://gitee.com/supervol/loong-springboot-study

(记得给个start,感谢)

Synchronized 概述

        在 Spring Boot 3 应用中,synchronized作为 Java 原生的线程同步机制,是实现本地锁(仅在当前 JVM 进程内生效)的基础工具,用于解决单实例应用中的并发安全问题。

Synchronized 核心

        synchronized是Java 的关键字,其核心作用是保证同一时刻只有一个线程执行特定代码块,从而避免多线程并发访问共享资源时出现的数据不一致(如脏读、重复修改等)问题。在 Spring Boot 3 中,它的本质是本地锁:仅对当前 JVM 进程内的线程有效,无法跨进程(如分布式部署的多实例应用)同步,这是与分布式锁(如 Redis 锁、ZooKeeper 锁)的核心区别。

Synchronized 使用

        在 Spring Boot 3 中,synchronized的使用方式与标准 Java 一致,主要有以下 3 种:

1. 修饰实例方法

        锁对象为当前对象实例this),即多个线程调用同一对象的该方法时会被同步。

@Service
public class StockService {
    private int stock = 100; // 共享资源
    
    // 修饰实例方法:锁为当前StockService实例(单例Bean时全局有效)
    public synchronized void deductStock() {
        if (stock > 0) {
            stock--;
            System.out.println("扣减成功,剩余库存:" + stock);
        } else {
            System.out.println("库存不足");
        }
    }
}

注:Spring Boot 默认 Bean 为单例,因此该锁对所有调用该 Bean 的线程生效。

2. 修饰静态方法

        锁对象为当前类的 Class 对象(如StockService.class),作用范围是整个类,即使多个实例也会被同步。

@Service
public class CounterService {
    private static int count = 0; // 静态共享资源
    
    // 修饰静态方法:锁为CounterService.class
    public static synchronized void increment() {
        count++;
        System.out.println("计数:" + count);
    }
}

3. 修饰代码块

        显式指定锁对象(可自定义),灵活性更高,能缩小同步范围以提升性能。

@Service
public class OrderService {
    private final Object lock = new Object(); // 自定义锁对象
    private int orderId = 0;
    
    public void createOrder() {
        // 仅同步关键代码块,锁为lock对象
        synchronized (lock) {
            orderId++;
            System.out.println("生成订单ID:" + orderId);
        }
        // 非关键代码(如日志、参数校验)无需同步,提升效率
        System.out.println("订单创建完成");
    }
}

Synchronized示例

        请参考项目地址中 springboot-lock/springboot-local-lock 模块代码。

Synchronized 原理

  synchronized的底层依赖 JVM 的对象监视器(Monitor) 机制,通过修改对象头中的Mark Word(存储锁状态)实现锁的获取与释放:

  • 当线程进入synchronized代码块时,会尝试获取锁对象的 Monitor,若成功则独占锁;
  • 其他线程会被阻塞并进入等待队列,直到持有锁的线程释放 Monitor(退出代码块)。

        Java 6 及以上对synchronized进行了优化,引入了锁升级机制(偏向锁 → 轻量级锁 → 重量级锁),大幅提升了低并发场景下的性能:

  • 偏向锁:无竞争时,仅记录线程 ID,几乎无开销;
  • 轻量级锁:轻度竞争时,通过 CAS(比较并交换)尝试获取锁,避免线程阻塞;
  • 重量级锁:重度竞争时,依赖操作系统互斥量实现,会导致线程阻塞(开销较大)。

Synchronized 场景

   synchronized适用于单实例 Spring Boot 应用,解决以下并发问题:

  1. 共享资源修改:如库存扣减、计数器累加、订单 ID 生成等;
  2. 临界区代码保护:如防止多线程同时执行初始化操作(如加载配置);
  3. 避免重复处理:如防止同一请求被多个线程重复处理(需配合幂等设计)。

Synchronized 注意

  1. 仅支持本地锁:多实例部署(分布式系统)时,synchronized无法跨 JVM 同步,需使用分布式锁(如 Redisson、Curator);
  2. 锁粒度问题:同步范围过大(如修饰整个方法)可能导致性能下降,建议用代码块缩小范围;
  3. Bean 作用域影响:若 Spring Bean 为原型(prototype),实例方法的synchronized锁仅对当前实例有效,可能无法实现全局同步(需改用静态方法或类锁);
  4. 不可中断性:持有锁的线程若阻塞(如 IO 操作),其他线程会一直等待,可考虑ReentrantLock(支持中断)作为替代。

总结

   synchronized是 Spring Boot 3 单实例应用中实现线程安全的简单有效工具,通过原生 Java 机制保证本地并发安全,适合低至中并发场景。但在分布式环境或需要更灵活锁控制(如超时、中断)的场景中,需结合其他同步方案(如分布式锁、ReentrantLock)使用。


网站公告

今日签到

点亮在社区的每一天
去签到