`

关于分布式锁

阅读更多
分布式锁
并发编程中的锁并发编程的锁机制:synchronized和lock。在单进程的系统中,当存
在多个线程可以同时改变某个变量时,就需要对变量或代码块做同步,使其在修改这种变量时能够
线性执行消除并发修改变量。而同步的本质是通过锁来实现的。为了实现多个线程在一个时刻同一个
代码块只能有一个线程可执行,那么需要在某个地方做个标记,这个标记必须每个线程都能看到,当标记
不存在时可以设置该标记,其余后续线程发现已经有标记了则等待拥有标记的线程结束同步代码块取消标记
后再去尝试设置标记。

分布式环境下,数据一致性问题一直是一个比较重要的话题,而又不同于单进程的情况。
分布式与单机情况下最大的不同在于其不是多线程而是多进程。多线程由于可以共享堆内存,
因此可以简单的采取内存作为标记存储位置。而进程之间甚至可能都不在同一台物理机上,
因此需要将标记存储在一个所有进程都能看到的地方。
常见的是秒杀场景,订单服务部署了多个实例,如
秒杀商品有4个,第一个用户购买3个,第二个用户购买2个,理想状态下第一个用户能购买成功,第二
个用户提示购买失败,反之亦然。而实际可能出现的情况是,两个用户都得到库存为4,第一个用户
买到了3个,更新库存之前,第二个用户下了2个商品的订单,更新库存为2,导致出错。

在上面的场景中,商品的库存是共享变量,面对高并发情形,需要保证对资源的访问互斥。在单机环境中,
java中其实提供了很多并发处理相关的API,但是这些API在分布式场景中就无能为力了。也就是
说单纯的java API 并不能提供分布式锁的能力。分布式系统中,由于分布式系统的分布性,即
多线程和多进程并且分布在不同机器中,synchronized和lock这两种锁将失去原有锁的效果,
需要我们自已实现分布式锁。

常见的分布式锁如下:
基于数据库实现分布式锁:有性能问题
基于缓存实现分布式锁,如redis
基于zookeeper实现分布式锁

使用setnx实现分布式锁
setnx key value
setnx是将key的值设为value,当且仅当key不存在。若给定的key已经存在,则setnx不做任何动作。
返回1,说明该进程获得锁,setnx将键(lock.id)的值设置为锁的超时时间,当前时间+加上锁的有效时间。
返回0,说明其他进程已经获得了锁,进程不能进入临界区。进程可以在一个循环中不断地尝试setnx操作,以获得锁。

存在死锁的问题

在线程释放锁,即执行del lock.id操作前,需要先判断锁是否已超时。如果锁已超时,那么锁可能已由其他线程
获得,这时直接执行del lock.id操作会导致把其他线程已获得的锁释放掉。

获取分布式锁
public boolean lock(long timeout,TimeUnit timeUnit) throws InterruptedException{
timeout = timeUnit.toMillis(timeout);
long time = timeout + System.currentTimeMillis();
lock.tryLock(timeout, timeUnit);
try{
while(true){
boolean hasLock = tryLock();
if(hasLock){
return true; //获得锁
}else if(timeout < System.currentTimeMillis()){
break;
}
Thread.sleep(1000);
}
}finally{
if(lock.isHeldByCurrentThread()){
lock.unlock();
}
}
return false;
}

public boolean tryLock(){
long time =  System.currentTimeMillis();
long timeout = 2000;
String expires = String.valueOf(timeout+time);
if(redisService.setnx("lock.id", expires)>0){
//获取锁,设置超时时间
setLockStatus(expires);
return true;
}else{
String locktime = redisService.get("lock.id");
//检查锁是否超时
if(locktime != null && Long.parseLong(locktime)<time){
String oldlocktime = redis.getset("lock.id",expires);
//旧值与当前时间比较
if(oldlocktime !=null && locktime.equals(oldlocktime)){
//获取锁,设置超时时间
setLockStatus(expires);
return true;
}
}
return false;
}
}

释放锁
public boolean unlock(){
if(lockHolder == Thread.currentThread()){
//判断锁是否超时,没有超时才将互斥量删除
if(lockExpiresTime > System.currentTimeMillis()){
redisService.del("lock.id");
}
lockHolder = null;
return true;
}else{
throws new IllegalMonitorStateException("无法执行解锁操作");
}
}

android入门实例:https://gitbook.cn/gitchat/activity/5d382e64b669c0566c335b32
0
0
分享到:
评论

相关推荐

    Java基于redis实现分布式锁代码实例

    Java基于Redis实现分布式锁代码实例 分布式锁的必要性 在多线程环境中,资源竞争是一个常见的问题。例如,在一个简单的用户操作中,一个线程修改用户状态,首先在内存中读取用户状态,然后在内存中进行修改,然后...

    分布式锁原理讲解视频资料

    分布式锁是一种在分布式系统中实现同步访问资源的关键技术。它允许多个节点在同一时间对共享资源进行操作,但确保任何时刻只有一个节点能持有锁并执行相应的操作。本视频资料深入浅出地讲解了分布式锁的原理、实现...

    分布式锁处理步骤

    分布式锁是一种在分布式系统中实现资源同步的关键技术,它确保在多节点环境下,同一时间只有一个节点可以访问或修改特定的共享资源,以防止数据不一致性和并发问题。在Oracle数据库中,分布式事务处理可能会导致...

    C#实操控制并发之Lock和Redis分布式锁

    本文将深入探讨C#中如何使用Lock和Redis分布式锁来解决并发问题,以秒杀系统为例进行阐述。 首先,让我们理解什么是并发控制。并发控制是指在多线程环境下确保数据的一致性和完整性,防止多个线程同时访问同一资源...

    C#.net Redis分布式锁源码实现

    在IT行业中,尤其是在大型分布式系统的设计与开发中,分布式锁是一种关键的同步机制。本篇文章将深入探讨如何在C#.NET环境下利用Redis实现分布式锁,以及相关的核心知识点。 首先,让我们理解什么是分布式锁。...

    redis实现分布式锁,自旋式加锁,lua原子性解锁

    在分布式系统中,为了保证数据的一致性和安全性,分布式锁是一种常见的解决方案。Redis作为一个高性能的键值存储系统,常被用作实现分布式锁的工具。本文将深入探讨如何使用Redis实现分布式锁,以及如何利用自旋式...

    redis分布式锁工具类

    现在很多项目单机版已经不满足了,分布式变得越受欢迎,同时也带来很多问题,分布式锁也变得没那么容易实现,分享一个redis分布式锁工具类,里面的加锁采用lua脚本(脚本比较简单,采用java代码实现,无须外部调用...

    分布式锁简单实现

    以下是一些关于分布式锁的重要知识点: 1. **锁的类型**: - **互斥锁(Mutex)**:确保任何时候只有一个客户端持有锁,防止数据竞争。 - **读写锁(Read-Write Lock)**:允许多个读操作同时进行,但在写操作时...

    redis分布式锁.zip

    Redis 分布式锁是分布式系统中解决并发控制和数据一致性问题的一种常见机制。在大型分布式应用中,单机锁无法满足需求,因为它们局限于单个服务器。Redis 的高可用性和低延迟特性使其成为实现分布式锁的理想选择。...

    浅谈分布式锁

    分布式锁是解决分布式系统中多个进程间共享资源互斥访问的一种方法,它保证了即使在分布式环境下,也能维持数据的一致性。随着互联网公司业务的不断扩展和技术的进步,分布式系统的数据量和业务复杂性大幅增加,...

    踩到一个关于分布式锁的非比寻常的BUG!.doc

    分布式锁是解决多节点间并发控制的关键技术,尤其在微服务架构中,确保同一资源在同一时刻仅被一个服务实例操作。Redisson 是一个流行的 Java 客户端,提供了对 Redis 的丰富支持,包括分布式锁的实现。其内部的...

    C++基于redis的分布式锁redisAPI

    本文将深入探讨如何使用C++结合Redis实现分布式锁,并详细讲解Redis API在C++中的应用,以及如何处理与Boost库的集成。 首先,Redis是一个高性能的键值存储数据库,广泛用于缓存、消息队列、分布式锁等场景。分布式...

    基于 Redis 的分布式锁

    分布式锁是分布式系统中用于同步资源访问的一种机制,它能够保证在分布式部署的应用系统中,同一时刻只允许一个客户端对共享资源进行操作。随着互联网业务的发展,分布式系统越来越多地成为企业架构的选择,因此...

    42_分布式锁是啥?对比下redis和zk两种分布式锁的优劣?.zip

    分布式锁是一种在分布式系统中实现同步访问资源的机制,它允许多个节点在同一时间对共享资源进行操作,而不会导致数据不一致或并发问题。在Java开发中,分布式锁的应用广泛,尤其是在微服务架构中,当服务间的通信...

    深入分析分布式锁的原理及特性.zip

    关于开源的分布式锁实现,Redis是一个广泛使用的解决方案。Redis提供了多种实现分布式锁的方法,如使用`SETNX`命令设置带有过期时间的键,或者使用`RedLock`算法,通过在多个Redis实例上创建锁来提高健壮性。`SETNX`...

    基于Redis的分布式锁的实现方案.pdf

    基于Redis的分布式锁的实现方案 本文讨论了分布式锁的实现方案,主要基于Redis实现分布式锁,以解决分布式系统中资源访问的同步问题。在分布式系统中,需要协调各个系统或主机之间的资源访问,以避免彼此干扰和保证...

    springboot基于redis分布式锁

    在现代的高并发系统中,分布式锁是一种非常重要的机制,用于协调多个节点间的资源访问,以确保数据的一致性和完整性。SpringBoot是一个流行的Java微服务框架,它简化了与各种技术栈的集成,包括Redis这样的高性能...

    redisson实现分布式锁

    在分布式系统中,锁是保证数据一致性的重要工具,而Redisson的分布式锁则为Java开发者提供了一种高效且可靠的解决方案。 首先,让我们深入理解分布式锁的概念。分布式锁是在分布式系统中,为了确保多个节点对共享...

    zk使用curator实现分布式锁

    ZooKeeper是一个高度可靠的分布式协调服务,它提供了诸如分布式锁、队列和配置管理等核心功能。Curator则是Apache ZooKeeper的一个客户端库,它简化了ZooKeeper的使用,提供了丰富的工具和策略,使得开发人员能够更...

    基于zookeeper的分布式锁简单实现

    分布式锁是一种在分布式系统中实现同步的技术,它允许多个节点在同一时刻访问共享资源。在大型分布式环境中,由于网络延迟和并发操作,简单的本地锁可能无法有效解决数据一致性问题。这时,Zookeeper,一个高可用的...

Global site tag (gtag.js) - Google Analytics