Spring Boot 分布式锁与并发控制的应用场景

 更新时间:2026年03月26日 11:48:47   作者:星辰徐哥  
本章主要介绍了SpringBoot分布式锁与并发控制的核心概念与使用方法,包括分布式锁的定义与特点、并发控制的定义与特点、SpringBoot与分布式锁的集成、SpringBoot的实际应用场景,感兴趣的朋友跟随小编一起看看吧

Spring Boot 分布式锁与并发控制

30.1 学习目标与重点提示

学习目标:掌握Spring Boot分布式锁与并发控制的核心概念与使用方法,包括分布式锁的定义与特点、并发控制的定义与特点、Spring Boot与分布式锁的集成、Spring Boot的实际应用场景,学会在实际开发中处理分布式锁与并发控制问题。
重点:分布式锁的定义与特点并发控制的定义与特点Spring Boot与分布式锁的集成Spring Boot的实际应用场景

30.2 分布式锁与并发控制概述

分布式锁与并发控制是Java开发中的重要组件,用于处理分布式系统中的并发访问问题。

30.2.1 分布式锁的定义

定义:分布式锁是一种用于在分布式系统中实现资源共享访问控制的机制,确保在同一时间只有一个进程或线程能够访问共享资源。
作用

  • 防止资源的并发修改。
  • 确保数据的一致性。
  • 提高系统的可靠性。

常见的分布式锁

  • Redis分布式锁:Redis是一种开源的内存数据库,支持分布式锁。
  • Zookeeper分布式锁:Zookeeper是一种开源的分布式协调服务,支持分布式锁。
  • Etcd分布式锁:Etcd是一种开源的分布式键值存储系统,支持分布式锁。

✅ 结论:分布式锁是一种用于在分布式系统中实现资源共享访问控制的机制,作用是防止资源的并发修改、确保数据的一致性、提高系统的可靠性。

30.2.2 并发控制的定义

定义:并发控制是指在多进程或多线程环境中,控制对共享资源的访问,防止数据不一致和并发冲突。
作用

  • 防止数据不一致。
  • 防止并发冲突。
  • 提高系统的性能。

常见的并发控制技术

  • 锁机制:包括悲观锁和乐观锁。
  • 事务机制:包括ACID属性。
  • 并发集合:包括ConcurrentHashMap和CopyOnWriteArrayList。

✅ 结论:并发控制是指在多进程或多线程环境中,控制对共享资源的访问,作用是防止数据不一致、防止并发冲突、提高系统的性能。

30.3 Spring Boot与分布式锁的集成

Spring Boot与分布式锁的集成是Java开发中的重要内容。

30.3.1 集成Redis分布式锁的步骤

定义:集成Redis分布式锁的步骤是指使用Spring Boot与Redis分布式锁集成的方法。
步骤

  1. 创建Spring Boot项目。
  2. 添加所需的依赖。
  3. 配置Redis。
  4. 创建分布式锁工具类。
  5. 创建业务层。
  6. 创建控制器类。
  7. 测试应用。

示例
pom.xml文件中的依赖:

<dependencies>
    <!-- Web依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Redis依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!-- 测试依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

application.properties文件中的配置:

# 服务器端口
server.port=8080
# Redis连接信息
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.database=0

分布式锁工具类:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisLock {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    private static final String LOCK_KEY = "product-lock";
    private static final long LOCK_EXPIRE_TIME = 30; // 锁的过期时间,单位秒
    public boolean tryLock(String lockValue) {
        Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(LOCK_KEY, lockValue, LOCK_EXPIRE_TIME, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(result);
    }
    public void releaseLock(String lockValue) {
        String value = stringRedisTemplate.opsForValue().get(LOCK_KEY);
        if (lockValue.equals(value)) {
            stringRedisTemplate.delete(LOCK_KEY);
        }
    }
}

实体类:

public class Product {
    private Long id;
    private String productId;
    private String productName;
    private double price;
    private int stock;
    public Product() {
    }
    public Product(Long id, String productId, String productName, double price, int stock) {
        this.id = id;
        this.productId = productId;
        this.productName = productName;
        this.price = price;
        this.stock = stock;
    }
    // Getter和Setter方法
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getProductId() {
        return productId;
    }
    public void setProductId(String productId) {
        this.productId = productId;
    }
    public String getProductName() {
        return productName;
    }
    public void setProductName(String productName) {
        this.productName = productName;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public int getStock() {
        return stock;
    }
    public void setStock(int stock) {
        this.stock = stock;
    }
    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", productId='" + productId + '\'' +
                ", productName='" + productName + '\'' +
                ", price=" + price +
                ", stock=" + stock +
                '}';
    }
}

Repository接口:

import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Repository
public class ProductRepository {
    private List<Product> products = new ArrayList<>();
    public ProductRepository() {
        products.add(new Product(1L, "P001", "手机", 1000.0, 100));
        products.add(new Product(2L, "P002", "电脑", 5000.0, 50));
        products.add(new Product(3L, "P003", "电视", 3000.0, 80));
        products.add(new Product(4L, "P004", "手表", 500.0, 200));
        products.add(new Product(5L, "P005", "耳机", 300.0, 150));
    }
    public List<Product> getAllProducts() {
        return products;
    }
    public Product getProductById(Long id) {
        return products.stream().filter(product -> product.getId().equals(id)).findFirst().orElse(null);
    }
    public void addProduct(Product product) {
        product.setId((long) (products.size() + 1));
        products.add(product);
    }
    public void updateProduct(Product product) {
        Product existingProduct = getProductById(product.getId());
        if (existingProduct != null) {
            existingProduct.setProductId(product.getProductId());
            existingProduct.setProductName(product.getProductName());
            existingProduct.setPrice(product.getPrice());
            existingProduct.setStock(product.getStock());
        }
    }
    public void deleteProduct(Long id) {
        products.removeIf(product -> product.getId().equals(id));
    }
}

Service类:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.UUID;
@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private RedisLock redisLock;
    public List<Product> getAllProducts() {
        return productRepository.getAllProducts();
    }
    public Product getProductById(Long id) {
        return productRepository.getProductById(id);
    }
    public void addProduct(Product product) {
        productRepository.addProduct(product);
    }
    public void updateProduct(Product product) {
        productRepository.updateProduct(product);
    }
    public void deleteProduct(Long id) {
        productRepository.deleteProduct(id);
    }
    public boolean reduceStock(Long id, int quantity) {
        String lockValue = UUID.randomUUID().toString();
        try {
            if (redisLock.tryLock(lockValue)) {
                Product product = productRepository.getProductById(id);
                if (product != null && product.getStock() >= quantity) {
                    product.setStock(product.getStock() - quantity);
                    productRepository.updateProduct(product);
                    return true;
                }
                return false;
            }
            return false;
        } finally {
            redisLock.releaseLock(lockValue);
        }
    }
}

控制器类:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/products")
public class ProductController {
    @Autowired
    private ProductService productService;
    @GetMapping("/")
    public List<Product> getAllProducts() {
        return productService.getAllProducts();
    }
    @GetMapping("/{id}")
    public Product getProductById(@PathVariable Long id) {
        return productService.getProductById(id);
    }
    @PostMapping("/add")
    public void addProduct(@RequestBody Product product) {
        productService.addProduct(product);
    }
    @PutMapping("/edit/{id}")
    public void editProduct(@PathVariable Long id, @RequestBody Product product) {
        product.setId(id);
        productService.updateProduct(product);
    }
    @DeleteMapping("/delete/{id}")
    public void deleteProduct(@PathVariable Long id) {
        productService.deleteProduct(id);
    }
    @PostMapping("/reduceStock/{id}/{quantity}")
    public boolean reduceStock(@PathVariable Long id, @PathVariable int quantity) {
        return productService.reduceStock(id, quantity);
    }
}

应用启动类:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class RedisLockApplication {
    public static void main(String[] args) {
        SpringApplication.run(RedisLockApplication.class, args);
    }
}

测试类:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class RedisLockApplicationTests {
    @LocalServerPort
    private int port;
    @Autowired
    private TestRestTemplate restTemplate;
    @Test
    void contextLoads() {
    }
    @Test
    void testGetAllProducts() {
        List products = restTemplate.getForObject("http://localhost:" + port + "/api/products/", List.class);
        assertThat(products).hasSize(5);
    }
    @Test
    void testReduceStock() {
        boolean result = restTemplate.postForObject("http://localhost:" + port + "/api/products/reduceStock/1/10", null, Boolean.class);
        assertThat(result).isTrue();
    }
}

✅ 结论:集成Redis分布式锁的步骤包括创建Spring Boot项目、添加所需的依赖、配置Redis、创建分布式锁工具类、创建业务层、创建控制器类、测试应用。

30.4 Spring Boot的实际应用场景

在实际开发中,Spring Boot分布式锁与并发控制的应用场景非常广泛,如:

  • 实现产品库存的并发扣减。
  • 实现用户账户的并发扣款。
  • 实现订单的并发创建。
  • 实现数据的并发更新。

示例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.UUID;
@Service
class ProductService {
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private RedisLock redisLock;
    public List<Product> getAllProducts() {
        return productRepository.getAllProducts();
    }
    public Product getProductById(Long id) {
        return productRepository.getProductById(id);
    }
    public void addProduct(Product product) {
        productRepository.addProduct(product);
    }
    public void updateProduct(Product product) {
        productRepository.updateProduct(product);
    }
    public void deleteProduct(Long id) {
        productRepository.deleteProduct(id);
    }
    public boolean reduceStock(Long id, int quantity) {
        String lockValue = UUID.randomUUID().toString();
        try {
            if (redisLock.tryLock(lockValue)) {
                Product product = productRepository.getProductById(id);
                if (product != null && product.getStock() >= quantity) {
                    product.setStock(product.getStock() - quantity);
                    productRepository.updateProduct(product);
                    return true;
                }
                return false;
            }
            return false;
        } finally {
            redisLock.releaseLock(lockValue);
        }
    }
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
class RedisLock {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    private static final String LOCK_KEY = "product-lock";
    private static final long LOCK_EXPIRE_TIME = 30;
    public boolean tryLock(String lockValue) {
        Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(LOCK_KEY, lockValue, LOCK_EXPIRE_TIME, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(result);
    }
    public void releaseLock(String lockValue) {
        String value = stringRedisTemplate.opsForValue().get(LOCK_KEY);
        if (lockValue.equals(value)) {
            stringRedisTemplate.delete(LOCK_KEY);
        }
    }
}
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Repository
class ProductRepository {
    private List<Product> products = new ArrayList<>();
    public ProductRepository() {
        products.add(new Product(1L, "P001", "手机", 1000.0, 100));
        products.add(new Product(2L, "P002", "电脑", 5000.0, 50));
        products.add(new Product(3L, "P003", "电视", 3000.0, 80));
        products.add(new Product(4L, "P004", "手表", 500.0, 200));
        products.add(new Product(5L, "P005", "耳机", 300.0, 150));
    }
    public List<Product> getAllProducts() {
        return products;
    }
    public Product getProductById(Long id) {
        return products.stream().filter(product -> product.getId().equals(id)).findFirst().orElse(null);
    }
    public void addProduct(Product product) {
        product.setId((long) (products.size() + 1));
        products.add(product);
    }
    public void updateProduct(Product product) {
        Product existingProduct = getProductById(product.getId());
        if (existingProduct != null) {
            existingProduct.setProductId(product.getProductId());
            existingProduct.setProductName(product.getProductName());
            existingProduct.setPrice(product.getPrice());
            existingProduct.setStock(product.getStock());
        }
    }
    public void deleteProduct(Long id) {
        products.removeIf(product -> product.getId().equals(id));
    }
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/products")
class ProductController {
    @Autowired
    private ProductService productService;
    @GetMapping("/")
    public List<Product> getAllProducts() {
        return productService.getAllProducts();
    }
    @GetMapping("/{id}")
    public Product getProductById(@PathVariable Long id) {
        return productService.getProductById(id);
    }
    @PostMapping("/add")
    public void addProduct(@RequestBody Product product) {
        productService.addProduct(product);
    }
    @PutMapping("/edit/{id}")
    public void editProduct(@PathVariable Long id, @RequestBody Product product) {
        product.setId(id);
        productService.updateProduct(product);
    }
    @DeleteMapping("/delete/{id}")
    public void deleteProduct(@PathVariable Long id) {
        productService.deleteProduct(id);
    }
    @PostMapping("/reduceStock/{id}/{quantity}")
    public boolean reduceStock(@PathVariable Long id, @PathVariable int quantity) {
        return productService.reduceStock(id, quantity);
    }
}
@SpringBootApplication
public class RedisLockApplication {
    public static void main(String[] args) {
        SpringApplication.run(RedisLockApplication.class, args);
    }
}
// 测试类
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class RedisLockApplicationTests {
    @LocalServerPort
    private int port;
    @Autowired
    private TestRestTemplate restTemplate;
    @Test
    void contextLoads() {
    }
    @Test
    void testGetAllProducts() {
        List products = restTemplate.getForObject("http://localhost:" + port + "/api/products/", List.class);
        assertThat(products).hasSize(5);
    }
    @Test
    void testReduceStock() {
        boolean result = restTemplate.postForObject("http://localhost:" + port + "/api/products/reduceStock/1/10", null, Boolean.class);
        assertThat(result).isTrue();
    }
}

输出结果

  • 访问http://localhost:8080/api/products/:返回所有产品信息。
  • 访问http://localhost:8080/api/products/reduceStock/1/10:返回true,表示库存扣减成功。

✅ 结论:在实际开发中,Spring Boot分布式锁与并发控制的应用场景非常广泛,需要根据实际问题选择合适的分布式锁和并发控制方法。

总结

本章我们学习了Spring Boot分布式锁与并发控制,包括分布式锁的定义与特点、并发控制的定义与特点、Spring Boot与分布式锁的集成、Spring Boot的实际应用场景,学会了在实际开发中处理分布式锁与并发控制问题。其中,分布式锁的定义与特点、并发控制的定义与特点、Spring Boot与分布式锁的集成、Spring Boot的实际应用场景是本章的重点内容。从下一章开始,我们将学习Spring Boot的其他组件、微服务等内容。

到此这篇关于Spring Boot 分布式锁与并发控制的应用场景的文章就介绍到这了,更多相关Spring Boot 分布式锁与并发控制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 常用输入字节流InputStream介绍

    常用输入字节流InputStream介绍

    下面小编就为大家带来一篇常用输入字节流InputStream介绍。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • 解决java.util.HashMap$Values cannot be cast to java.ut的问题

    解决java.util.HashMap$Values cannot be cast to java.ut的问题

    这篇文章主要介绍了解决java.util.HashMap$Values cannot be cast to java.ut的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 简单谈谈Spring Ioc原理解析

    简单谈谈Spring Ioc原理解析

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框架的IOC的理解以及谈谈我对Spring Ioc的理解。
    2018-09-09
  • 详解如何在Java中重写equals()和hashCode()方法

    详解如何在Java中重写equals()和hashCode()方法

    在 Java 中,equals() 和 hashCode() 方法是 Object 类中定义的重要方法,它们用于比较对象的相等性以及计算对象的哈希值,本文将详细介绍如何在 Java 中重写 equals() 和 hashCode() 方法,并讨论其最佳实践,需要的朋友可以参考下
    2024-08-08
  • Spring Boot中使用RabbitMQ 生产消息和消费消息的实例代码

    Spring Boot中使用RabbitMQ 生产消息和消费消息的实例代码

    本文介绍了在SpringBoot中如何使用RabbitMQ进行消息的生产和消费,详细阐述了RabbitMQ中交换机的作用和类型,包括直连交换机、主题交换机、扇出交换机和头交换机,并解释了各自的消息路由机制,感兴趣的朋友一起看看吧
    2024-10-10
  • java类的定义与使用举例详解

    java类的定义与使用举例详解

    这篇文章主要给大家介绍了关于java类的定义与使用的相关资料,类的方法是用来定义类的行为,在方法中通过操作类的成员变量、编写业务逻辑、返回 结果等实现类的业务行为,需要的朋友可以参考下
    2023-11-11
  • 浅谈java中守护线程与用户线程

    浅谈java中守护线程与用户线程

    本篇文章主要介绍了浅谈java中守护线程与用户线程,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • 解决idea 拉取代码出现的 “ Сannot Run Git Cannot identify version of git executable: no response“的问题

    解决idea 拉取代码出现的 “ Сannot Run Git Cannot identify version of

    这篇文章主要介绍了解决idea 拉取代码出现的 “ Сannot Run Git Cannot identify version of git executable: no response“的问题,需要的朋友可以参考下
    2020-08-08
  • 详解SpringBoot实现fastdfs防盗链功能的示例代码

    详解SpringBoot实现fastdfs防盗链功能的示例代码

    我们可以通过fastdfs实现一个分布式文件系统,如果fastdfs部署在外网,那么任何一个人知道了上传接口,就可以实现文件的上传和访问。那么如何阻止他人访问我们fastdfs服务器上的文件呢?此处就需要使用fastdfs的防盗链功能,本文就来讲讲如何实现这一功能
    2022-10-10
  • 全网最精细详解二叉树,2万字带你进入算法领域

    全网最精细详解二叉树,2万字带你进入算法领域

    大家好,我是哪吒,一个热爱编码的Java工程师,本着"欲速则不达,欲达则欲速"的学习态度,在程序猿这条不归路上不断成长,所谓成长,不过是用时间慢慢擦亮你的眼睛,少时看重的,年长后却视若鸿毛,少时看轻的,年长后却视若泰山,成长之路,亦是渐渐放下执念,内心归于平静的旅程
    2021-08-08

最新评论