Java 分布式锁

Java分布式锁详解:概念、实现与应用 分布式锁是一种在分布式系统或集群环境中用于控制多个进程/线程对共享资源进行互斥访问的协调机制。在单机系统中,我们可以使用Java内置的关键字或等实现线程间的互斥访问,但在分布式环境下,这些本地锁机制无法跨JVM工作,因此需要分布式锁来协调不同节点上的进程。分布式锁的核心目的是在分布式系统中实现跨进程的互斥访问,确保在同一时间只有一个客户端(可能位于不同物理机器上)能够执行特定的操作或访问特定的资源。 阅读详情
AI摘要

分布式锁用于解决分布式系统中多节点对共享资源并发访问的竞争问题。Java中实现分布式锁的方式有基于数据库(唯一约束、行锁或表锁、version乐观锁)、基于Redis、基于Zookeeper,还有仅作了解的基于etcd的实现,每种方式都有其原理和特点。

        分布式锁主要用于解决在分布式系统中多个节点对共享资源进行并发访问时可能出现的竞争问题。

在Java中实现分布式锁的方式主要有以下几种:

基于数据库的实现

(1)唯一约束

        通过数据库表中设置唯一键约束来保证只有一个客户端可以获取到锁。通常会有一张专门的锁表,包含锁名称和锁的持有者信息等字段。

CREATE TABLE distributed_locks (
    lock_name VARCHAR(255) PRIMARY KEY,
    owner_info VARCHAR(255) NOT NULL
);

        该代码示例展示了如何使用上述表来获取和释放锁,并执行相应的业务逻辑(例如更新库存),在请求A对业务进行操作的时候,假设请求B也进入到此方法,则会由于锁表的唯一索引lock_name而导致插入失败,导致其操作被拒绝,而主键则需要针对不同业务场景设置,不同业务场景不会触发锁机制。

    public void operateStock(Integer num) {
        String lockName = "product_stock_update_lock"; // 锁名称,如:业务编码
        String ownerId = "d2d00005sa5s512"; // 当前实例标识符,如:用户id

        // SQL == "INSERT INTO distributed_locks(lock_name, owner_info) VALUES (?, ?)"
        // 加锁插入成功返回true
        boolean gotLock = acquireLock(lockName, ownerId);
        if (gotLock) {
            try {
                // 执行业务逻辑,如更新指定物料库存
                //SQL == "UPDATE products SET stock = stock - #{num} WHERE product_id = '001' AND stock > 0";
                updateProductStock(num);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // SQL == "DELETE FROM distributed_locks WHERE lock_name = ? AND owner_info = ?"
                releaseLock(lockName, ownerId);
            }
        } else {
            System.out.println("Failed to acquire lock.");
        }
    }

(2)行锁或表锁

        在查询语句后面增加for update,数据库会在查询过程中给数据库表增加排他锁,当某条记录被加上排他锁之后,其他线程无法再在该行记录上增加排他锁,而事务提交后会自动释放锁。

    @Autowired
    private ProductMapper productMapper;

    @Transactional
    public void updateProductStock(String productId) {
        //查询并加锁   @Select("SELECT * FROM products WHERE product_id = #{productId} FOR UPDATE")
        Product product = productMapper.selectForUpdate(productId);
        if (product == null || product.getStock() <= 0) {
            System.out.println("库存不足或产品不存在");
            return;
        }
        
        // 更新库存  @Update("UPDATE products SET stock = stock - 1 WHERE product_id = #{productId}")
        int rowsAffected = productMapper.updateStock(productId);
        if (rowsAffected > 0) {
            System.out.println("库存更新成功");
        } else {
            System.out.println("未能成功更新库存");
        }
    }

(3)version乐观锁

        乐观锁是一种处理并发控制的策略,它假设数据冲突的概率较低,因此不会在读取数据时加锁。相反,它会在更新数据时检查数据是否被其他事务修改过。这通常通过一个版本号(version)字段或时间戳来实现。

        读取数据:当一个事务读取数据时,同时获取该记录的版本号或时间戳。
        修改数据:当事务尝试更新数据时,它会使用版本号作为条件的一部分进行更新操作。

CREATE TABLE products (
    product_id VARCHAR(255) PRIMARY KEY,
    stock INT NOT NULL,
    version INT DEFAULT 0
);
    @Autowired
    private ProductMapper productMapper;

    @Transactional
    public void updateProductStock(String productId) {
        // 查询并加锁
        // @Select("SELECT product_id,stock,version FROM products WHERE product_id = #{productId} FOR UPDATE")
        Product product = productMapper.selectForUpdate(productId);
        if (product == null || product.getStock() <= 0) {
            System.out.println("库存不足或产品不存在");
            return;
        }

        // 尝试更新库存,并检查版本号
        // @Update("UPDATE products SET stock = stock - 1, version = version + 1 WHERE product_id = #{productId} AND version = #{version}")
        int rowsAffected = productMapper.updateStockWithVersion(productId, product.getVersion());
        if (rowsAffected > 0) {
            System.out.println("库存更新成功");
        } else {
            System.out.println("库存更新失败,可能已被其他事务更新");
            // 这里可以根据业务需求选择重试或者抛出异常等处理方式
        }
    }



基于Redis的实现

        使用Redis实现分布式锁是一种高效且广泛采用的方法,特别适合于需要高吞吐量和低延迟的场景。Redis通过其原子操作命令提供了一种简单而有效的机制来实现分布式锁。

SET resource_name my_random_value NX PX 30000

        NX 表示仅在键不存在时设置键。
        PX 30000 设置键的过期时间为30秒,防止死锁(如果客户端崩溃或网络问题导致无法释放锁)。

        RedisTemplate实现分布式锁

        编写工具类

@Component
public class MyRedisLock {

    private final RedisTemplate<String, String> redisTemplate;

    @Autowired
    // 自Spring 4.3起,如果只有一个构造函数,可以省略@Autowired注解
    public MyRedisLock(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    // Lua 脚本用于释放锁
    private static final String UNLOCK_SCRIPT =
            "if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) else return 0 end";

    // Lua 脚本用于续期锁
    private static final String RENEW_LOCK_SCRIPT =
            "if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('PEXPIRE', KEYS[1], ARGV[2]) else return 0 end";

    // 锁的前缀,用于区分不同的锁
    private static final String LOCK_PREFIX = "lock:";

    // 续期锁的时间间隔(毫秒)
    private static final long RENEW_INTERVAL_MS = 2000;


    /**
     尝试获取锁
     @param lockKey   锁的键名
     @param expireMs  锁的过期时间(毫秒)
     @param operateId 锁的值
     @return   如果成功获取锁,返回 true;否则返回 false
     **/
    public boolean tryLock(String lockKey, long expireMs, String operateId) {
        Boolean result = redisTemplate.opsForValue().setIfAbsent(LOCK_PREFIX + lockKey, operateId, expireMs, TimeUnit.MILLISECONDS);     // setIfAbsent实现上锁
        return result != null && result;
    }

    /**
     尝试获取锁并自动续期
     @param lockKey   锁的键名
     @param expireMs  锁的过期时间(毫秒)
     @param operateId 锁的值
     @return   如果成功获取锁,返回锁的唯一标识符;否则返回 null
     **/
    public boolean tryLockWithRenewal(String lockKey, long expireMs, String operateId) {
        Boolean result = redisTemplate.opsForValue().setIfAbsent(LOCK_PREFIX + lockKey, operateId, expireMs, TimeUnit.MILLISECONDS);        // setIfAbsent实现上锁
        if (result != null && result) {
            // 启动续期线程
            startRenewalThread(lockKey, operateId, expireMs);
            return true;
        }
        return false;
    }

    /**
     释放锁
     @param lockKey   锁的键名
     @param operateId 锁的值(用于验证是否是持有锁的客户端)
     @return  如果成功释放锁,返回 true;否则返回 false
     **/
    public boolean unlock(String lockKey, String operateId) {
        DefaultRedisScript<Long> script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class);
        // 执行lua脚本,参数解释下:
        // 第一个参数script为lua脚本
        // 第二个参数为key的集合,会依次替换lua脚本中的KEYS[]数组的数据,默认1开始
        // 第三个参数为参数集合,会依次替换lua脚本中的ARGVS[]数组的数据,默认1开始
        Long result = redisTemplate.execute(script, Collections.singletonList(LOCK_PREFIX + lockKey), operateId);
        return result != null && result == 1L;
    }

    /**
     自动续期锁
     @param lockKey   锁的键名
     @param operateId 锁的值(用于验证是否是持有锁的客户端)
     @param expireMs  锁的过期时间(毫秒)
     @return  如果成功续期,返回 true;否则返回 false
     **/
    public boolean renewLock(String lockKey, String operateId, long expireMs) {
        DefaultRedisScript<Long> script = new DefaultRedisScript<>(RENEW_LOCK_SCRIPT, Long.class);
        Long result = redisTemplate.execute(script, Collections.singletonList(LOCK_PREFIX + lockKey), operateId, String.valueOf(expireMs));
        return result != null && result == 1L;
    }

    /**
     启动续期线程
     @param lockKey   锁的键名
     @param operateId 锁的值
     @param expireMs  锁的过期时间(毫秒)
     **/
    private void startRenewalThread(final String lockKey, final String operateId, final long expireMs) {
        Thread renewalThread = new Thread(() -> {
            try {
                while (true) {
                    // 每隔一段时间续期一次,需要确保间隔时间小于过期时间,过期或释放锁将无法续费
                    Thread.sleep(RENEW_INTERVAL_MS);
                    if (!renewLock(lockKey, operateId, expireMs)) {  // 续锁操作
                        // 如果续期失败,直接结束守护线程,停止锁续期行为。
                        // 这里说明下,删除锁和续锁都需要验证lockValue,这个上锁时通过uuid创建的,其他线程肯定获取的都不一致,这样确保续锁行为只能是自己的守护线程才可以操作;如果续锁失败了,则说明是主线程完成任务删除了key锁,所以这里守护线程也可以结束了
                        break;
                    }
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        renewalThread.setDaemon(true);  // 设置为守护线程
        renewalThread.start();
    }
}

        代码示例:常规锁

    @Autowired
    private MyRedisLock redisLock;

    // 锁的默认过期时间(毫秒)
    private static final long DEFAULT_EXPIRE_TIME_MS = 5000;

    public void testLock() throws InterruptedException {
        String lockKey = "my_distributed_lock";
        //进程标识ID
        String operateId = java.util.UUID.randomUUID().toString();
        if (redisLock.tryLock(lockKey, DEFAULT_EXPIRE_TIME_MS, operateId)) {
            System.out.println(" 获取到锁,开始执行任务...");
            try {
                // 执行业务逻辑
                Thread.sleep(5000); // 模拟耗时操作
                System.out.println(Thread.currentThread().getName() + " 任务执行完成");
            } finally {
                if (redisLock.unlock(lockKey, operateId)) {
                    System.out.println(Thread.currentThread().getName() + " 成功释放锁");
                } else {
                    System.out.println(Thread.currentThread().getName() + " 释放锁失败,锁可能已被其他客户端删除");
                }
            }
        } else {
            System.out.println(Thread.currentThread().getName() + " 未能获取到锁");
        }
    }

        代码示例:续费线程锁

    @Autowired
    private MyRedisLock redisLock;

    // 锁的默认过期时间(毫秒)
    private static final long DEFAULT_EXPIRE_TIME_MS = 5000;

    public void testLock() throws InterruptedException {
        String lockKey = "my_distributed_lock";
        //进程标识ID
        String operateId = java.util.UUID.randomUUID().toString();
        // 尝试获取锁并自动续期
        if ( redisLock.tryLockWithRenewal(lockKey, DEFAULT_EXPIRE_TIME_MS, operateId)) {
            try {
                // 执行业务逻辑
                Thread.sleep(8000); 
                System.out.println(Thread.currentThread().getName() + " 任务执行完成");
            } finally {
                // 释放锁
                boolean unlockSuccess = redisLock.unlock(lockKey, operateId);
                if (unlockSuccess) {
                    System.out.println(Thread.currentThread().getName() + " 成功释放锁");
                } else {
                    System.out.println(Thread.currentThread().getName() + " 释放锁失败,锁可能已被其他客户端删除");
                }
            }
        } else {
            System.out.println(Thread.currentThread().getName() + " 未能获取到锁");
        }
    }



基于Zookeeper的实现

        基本原理

  • 创建临时顺序节点:客户端尝试在特定路径下创建一个临时顺序节点(例如/locks/lock-),以表示对锁的竞争。
  • 判断是否获得锁:检查自己创建的节点是否是该路径下所有子节点中最小的一个。如果是,则表示获得了锁;如果不是,则监听前一个节点(即比自己小的那个节点)的变化。
  • 监听前一节点删除事件:如果当前节点不是最小节点,则需要等待直到前一节点被删除(意味着前一客户端释放了锁),然后重新检查是否可以获得锁。
  • 释放锁:当业务逻辑执行完毕后,客户端可以主动删除自己创建的节点来释放锁。此外,由于使用的是临时节点,如果客户端崩溃或与ZooKeeper断开连接,该节点也会自动被删除。

        引入依赖(一个用于简化ZooKeeper操作的框架)

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>5.2.0</version>
</dependency>

        代码示例

    private static final String ZK_ADDRESS = "localhost:2181";
    private static final String LOCK_PATH = "/distributed_lock_example";

    public void operate() throws Exception {
        // 创建CuratorFramework实例
        CuratorFramework client = CuratorFrameworkFactory.newClient(ZK_ADDRESS, new ExponentialBackoffRetry(1000, 3));
        client.start();
        // 使用InterProcessMutex作为分布式锁
        InterProcessMutex lock = new InterProcessMutex(client, LOCK_PATH);
        try {
            // 获取锁
            lock.acquire(); 
            //业务操作代码
            this.performBusinessLogic();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (lock.isAcquiredInThisProcess()) {
                try {
                    // 释放锁
                    lock.release(); 
                    System.out.println("Lock released.");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            // 关闭客户端
            client.close(); 
        }
    }

    private static void performBusinessLogic() throws InterruptedException {
        // 模拟业务逻辑处理
        System.out.println("Performing some operations...");
        Thread.sleep(5000); // 暂停5秒模拟长时间操作
    }



基于etcd的实现(仅了解)

       类似于Zookeeper,etcd也提供了类似的分布式协调服务,可以通过创建租约(lease)并附加到关键路径上来实现分布式锁。Etcd支持事务、watch机制等功能,使得它同样适用于构建分布式锁。

Java 分布式锁:Redisson、Zookeeper、Spring 提供的 Redis 分布式锁封装详解 阅读详情

相关推荐

【Java实现分布式锁的几种方式】

【Java实现分布式锁的几种方式】

学无止境 1041

java 分布式锁

  在java的分布式系统中,有时候会出现不同的服务操作同一个资源的情况,如交易系统和充值系统都要操作用户账户,分布式锁为解决分布式系统中多个应用同时访问同一个资源的问题。 java的分布式锁主要有三种实现方式: 基于数据库的分布式锁 基于缓存的分布式锁 基于zookeeper的分布式锁 下面对这三种方式具体分析一下 1.基于数据库的分布式锁 数据库实现分布式锁方式比较多,如悲观锁(...

baixiaozheng的博客 7536

【Java分布式锁都有哪几种实现方式】

【Java分布式锁都有哪几种实现方式】

学无止境 966

分布式锁三种实现方式(数据库实现,缓存Redis等,Zookeeper)

分布式锁三种实现方式: 1. 基于数据库实现分布式锁; 2. 基于缓存(Redis等)实现分布式锁; 3. 基于Zookeeper实现分布式锁; 一, 基于数据库实现分布式锁 1. 悲观锁 利用select … where … for update 排他锁 注意: 其他附加功能与实现一基本一致,这里需要注意的是“where name=lock ”,name字段必须要走索引,否则会锁表...

1084

Java Spring 框架的分布式锁实现

在分布式系统中,多个服务节点可能会同时访问共享资源,为了保证数据的一致性和避免并发问题,需要使用分布式锁。本文的目的是介绍在 Java Spring 框架中实现分布式锁的多种方法,范围涵盖了基于 Redis、ZooKeeper 和数据库的分布式锁实现。

Java大师兄的博客 1142

离线安装vue脚手架,内网安装@vue/cli

公司开发环境使用内网,无法用外网,搭建环境的时候,发现内网系统没有安装vue脚手架,我搜了很多文章,发现他们的方法对我都不适用,然后就自己摸索,最终皇天不负有心人,终于被我安装上了,一下是我内网离线安装vue/cli的方法,希望能帮助到有需要的小伙伴! 因为npm被集成在nodejs中,而安装nodejs只需要把nodejs安装包copy到内网电脑安装就行,比较简单,这里就不多做演示。 在外网电脑上,使用npm install -g xxxx命令下载好我们所需要的各个安装包,比如: npm insta

Liberty_yes的博客 1万+

Java分布式锁

现在正是金三银四的春招高潮,前阵子小编一直在搭建自己的网站,并整理了全套的**【一线互联网大厂Java核心面试题库+解析】:包括Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等**《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

2401_83641314的博客 996

尚硅谷课程【笔记】——大数据之Shell【一】

【【尚硅谷】Shell脚本从入门到实战】笔记

n04j04h06的博客 1319

java中分布式锁

(1)使用 SETNX 命令尝试给指定的键(即锁的名称)设置一个值,如果设置成功,则表示当前节点获得锁,可以执行业务逻辑。(4)如果当前节点不是最小的子节点,则监听前一个子节点(即序号小于当前节点的最大节点)的删除事件。(3)如果当前节点获得锁后,执行完业务逻辑,需要释放锁,则使用 DEL 命令删除指定的键即可。(6)如果当前节点获得锁后,执行完业务逻辑,需要释放锁,则删除自己创建的临时子节点即可。(3)获取父节点下所有子节点,如果当前节点是最小的子节点,则表示当前节点获得锁。

cpy1356140308的博客 423

Windows Server 2012评估版过期自动关机问题:两种高效解决方案详解

本文针对Windows Server 2012评估版过期导致的自动关机问题,提供了两种高效解决方案。一是通过slmgr.vbs命令重置授权,临时延长评估期;二是使用DISM工具将评估版转换为正式版,一劳永逸。文章详细解析了两种方法的操作步骤、注意事项及适用场景,帮助用户快速恢复服务器稳定运行。

pytorchlight8的博客 1195

【Qt开发教程】网络代理QNetworkProxy类详解及实战应用

QNetworkProxy 提供了一种灵活而强大的方式来配置和管理网络代理,通过设置代理类型、主机、端口和认证信息,可以使应用程序的所有网络请求通过代理服务器进行。结合 QNetworkProxyFactory 可以实现动态代理选择和自动配置,提高应用的网络通信能力和安全性。在实际应用中,通过合理设置代理、处理代理认证和错误情况,可以确保应用程序在复杂的网络环境中稳定运行,为用户提供可靠的网络访问体验。

科技改变人类,技术成就未来 1542

使用Java实现分布式锁

在分布式环境中,多个进程可能需要同时访问某个共享资源,分布式锁可以确保在任何时刻只有一个进程能够访问该资源,从而避免数据竞争和不一致性问题。在这篇文章中,我将详细介绍如何使用Java实现分布式锁,并结合实际代码示例,帮助大家更好地理解和应用分布式锁技术。通过以上内容,我们介绍了如何使用Java实现分布式锁,重点演示了基于Redis和Zookeeper的分布式锁的实现和使用方法。分布式锁有多种实现方式,包括基于数据库的分布式锁、基于Redis的分布式锁、基于Zookeeper的分布式锁等。

微赚淘客开发者博客 1262

【教程4>第3章>第1节】通信系统高阶调制解调概述

高阶调制(High Order Modulation)是一种先进的数字调制技术,旨在通过增加每个符号携带的信息比特数来提高无线通信系统的数据传输速率和频谱效率。这种技术特别适用于具有较高信噪比(Signal-to-Noise Ratio, SNR)的通信环境,例如卫星通信、光纤通信以及一些高质量的无线通信链路。在数字通信中,调制是将数字信号(比特流)转换为适合在物理信道上传输的模拟信号的过程。高阶调制通过使用更多的信号状态或星座点来表示不同的比特组合,从而在一个符号周期内传输更多的信息。

FPGA/MATLAB学习教程/源码/项目合作开发 1703

【java的本地锁到分布式锁介绍】

在理解锁实现原理之前先了解一下Java的对象头和Monitor,在JVM中,对象是分成三部分存在的:对象头、实例数据、对其填充。实例数据和对其填充与synchronized无关,这里简单说一下(我也是阅读《深入理解Java虚拟机》学到的,读者可仔细阅读该书相关章节学习)。实例数据存放类的属性数据信息,包括父类的属性信息,如果是数组的实例部分还包括数组的长度,这部分内存按4字节对齐;对其填充不是必须部分,由于虚拟机要求对象起始地址必须是8字节的整数倍,对齐填充仅仅是为了使字节对齐。

weixin_47068446的博客 1257

JAX/JAXlib GPU 加速版本安装教程(CUDA)

本文介绍了在Windows WSL2+Ubuntu22.04环境下配置JAX/JAXlib GPU加速版本的详细步骤。使用RTX 4060显卡,安装CUDA 12.4和cuDNN 8.9.7驱动,通过Miniconda创建Python 3.9虚拟环境。具体步骤包括:安装Miniconda、配置CUDA环境变量、安装cuDNN驱动、下载并安装JAX/JAXlib。最后通过测试代码验证GPU加速功能,成功检测到GPU并完成矩阵运算。整个过程配有详细命令和截图说明,适合需要搭建JAX GPU开发环境的用户参考。

猿小白的博客 627

基于FPGA的UDP 通信(一)

手头的FPGA开发板上有一个千兆网口,最近准备做一下以太网通信的内容。本文先介绍基本的理论知识。 FPGA芯片型号:xc7a35tfgg484-2 网口芯片:RTL8211 网络接口:RJ45

记录所学,分享知识,结识挚友 8360

【java】 分布式锁实现和选型

Java 分布式锁的实现和选型

qq_42320804的博客 1344

【Go语言实战】(26) 分布式搜索引擎

基于go语言的分布式搜索引擎

面向生活编程 2380

Java中常见的几种分布式锁介绍及实战应用

锁在JAVA中是一个非常重要的概念,尤其是在当今的互联网时代,高并发的场景下,更是离不开锁。那么锁到底是什么呢?在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制。锁旨在强制实施互斥排他、并发控制策略。咱们举一个生活中的例子:大家都去过超市买东西,如果你随身带了包呢,要放到储物柜里。咱们把这个例子再极端一下,假如柜子只有一个,现在同时来了3个人A,B,C,都要往这个柜子里放东西。这个场景就构造了一个多线程,多线程自然离不开锁。

qq_46601365的博客 4431

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Java中的分布式锁实现原理

分布式锁在分布式系统中扮演了重要角色,通过有效的锁机制,可以确保多个实例对共享资源的互斥访问。在实际应用中,应根据具体业务需求和系统特点选择合适的分布式锁实现方式,并遵循最佳实践,以确保系统的高可用性和数据一致性。与本地锁不同,分布式锁需要在多个节点之间协同工作,以实现跨进程和跨节点的同步。通过分布式锁,可以确保任务调度的互斥性。在某些场景中,锁的获取需要考虑公平性,即按照请求的顺序依次获取锁。分布式锁的实现方式有多种,常见的有基于数据库、缓存(如Redis)和ZooKeeper的实现方式。

微赚淘客系统开发者博客 1157

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

《Redis实现分布式锁》一、JAVA实现Redis分布式锁

在Java中,关于锁我想大家都很熟悉。在并发编程中,我们通过锁,来避免由于竞争而造成的数据不一致问题。通常,我们以synchronized 、Lock来使用它。 但是Java中的锁,只能保证在同一个JVM进程内中执行。如果在分布式集群环境下呢? 一、分布式锁 分布式锁,是一种思想,它的实现方式有很多。比如,我们将沙滩当做分布式锁的组件,那么它看起来应该是这样的: 加锁 在沙滩上踩一脚,留下自己的脚印,就对应了加锁操作。其他进程或者线程,看到沙滩上已经有脚印,证明锁已被别人持有,则等待。 解锁 把脚

后端研发工程师Marion的博客 1327

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

java redis 分布式锁_Java基于redis实现分布式锁

前言分布式锁,实在原理是就是多台机械,去争抢一个资源,谁争抢乐成,那么谁就持有了这把锁,然后去执行后续的营业逻辑,执行完毕后,把锁释放掉。可以通过多种途径实现分布式锁,例如行使数据库(mysql等),插入一条纪录(唯一索引),谁插入乐成,谁就持有锁;还可通过zookeeper来实现分布式锁,谁建立节点乐成,谁就持有锁。本文先容通过redis来实现分布式锁。本文使用springboot提供的Redi...

weixin_29731583的博客 762
上一篇: Java锁
下一篇: Redisson分布式锁框架
快乐吃手手  :  )
博客等级 码龄6年 119粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值