AtomicInteger和reids 来做分布式锁
时间: 2023-10-27 16:30:49 浏览: 83
AtomicInteger和Redis都可以用来实现分布式锁,但是它们的实现方式有所不同。
AtomicInteger是Java中的一个原子类,可以保证在高并发的情况下,多个线程对其进行操作时的线程安全性。在实现分布式锁时,可以使用AtomicInteger作为计数器,每次获取锁时将计数器加1,释放锁时将计数器减1,当计数器的值为0时表示锁已经被释放。
Redis是一种内存数据库,支持多种数据结构和操作,其中包括分布式锁。在Redis中,可以使用set命令进行锁的设置,将锁的名字作为key,将随机生成的value作为value,设置过期时间来保证锁的自动释放。获取锁时,需要使用set命令的NX(不存在则创建)选项来避免锁的重复创建,释放锁时,需要使用Lua脚本来保证原子性。
在实际应用中,选择使用哪种方式实现分布式锁,需要根据具体的场景和需求来进行选择。如果对于性能要求比较高的场景,可以考虑使用AtomicInteger来实现分布式锁,如果对于可靠性要求比较高的场景,可以考虑使用Redis来实现分布式锁。
相关问题
AtomicInteger和reidis配合实现分布式锁
AtomicInteger是Java中的一个原子类,它提供了原子性的操作,可以保证多个线程对其进行操作时是线程安全的。而Redis是一个高性能的key-value存储系统,它支持分布式部署和多种数据结构,可以用来实现分布式锁。
在实现分布式锁时,可以使用AtomicInteger作为计数器,每次获取锁时将计数器加1,释放锁时将计数器减1。同时,使用Redis作为存储介质,将计数器的值写入到Redis中,并设置一个过期时间,确保锁的自动释放。
具体实现步骤如下:
1. 在Redis中设置一个key,表示需要加锁的资源,同时设置一个过期时间,避免死锁。
2. 使用AtomicInteger作为计数器,每次获取锁时将计数器加1,释放锁时将计数器减1。
3. 将计数器的值写入到Redis中,使用Redis的setnx操作保证只有一个线程能够获取锁。
4. 如果setnx操作返回0,则说明有其他线程已经获取了锁,此时需要等待一段时间后重新尝试获取锁。
5. 当获取到锁后,执行业务逻辑,使用完后释放锁,将计数器的值写入Redis中,并将Redis中的key删除。
需要注意的是,在使用Redis实现分布式锁时,要考虑到网络延迟、Redis宕机等问题,确保锁的正常释放。同时需要保证锁的粒度尽量小,避免因为锁的竞争导致性能瓶颈。
AtomicInteger和reidis配合实现分布式锁代码
使用AtomicInteger和redis配合实现分布式锁的代码如下所示:
```java
public class DistributedLock {
private final static String LOCK_PREFIX = "distributed_lock:";
private final static int LOCK_EXPIRE = 60 * 1000; // 锁过期时间
private Jedis jedis;
private String lockKey;
private AtomicInteger counter = new AtomicInteger(0);
private int lockCount = 0;
public DistributedLock(Jedis jedis, String lockKey) {
this.jedis = jedis;
this.lockKey = LOCK_PREFIX + lockKey;
}
/**
* 获取分布式锁
* @return true:获取锁成功;false:获取锁失败
*/
public boolean lock() {
String value = String.valueOf(Thread.currentThread().getId());
long expireTime = System.currentTimeMillis() + LOCK_EXPIRE + 1;
// 尝试获取锁
if (jedis.setnx(lockKey, value) == 1) {
jedis.expire(lockKey, LOCK_EXPIRE);
lockCount = 1;
return true;
}
// 判断是否重入
if (value.equals(jedis.get(lockKey))) {
jedis.expire(lockKey, LOCK_EXPIRE);
lockCount = 1;
return true;
}
// 获取锁失败,等待其他线程释放锁
while (System.currentTimeMillis() < expireTime) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (jedis.setnx(lockKey, value) == 1) {
jedis.expire(lockKey, LOCK_EXPIRE);
lockCount = 1;
return true;
}
if (value.equals(jedis.get(lockKey))) {
jedis.expire(lockKey, LOCK_EXPIRE);
lockCount = 1;
return true;
}
}
return false;
}
/**
* 释放分布式锁
*/
public void unlock() {
if (lockCount == 1) {
jedis.del(lockKey);
} else {
int count = counter.decrementAndGet();
if (count == 0) {
jedis.del(lockKey);
}
}
}
/**
* 重入分布式锁
*/
public boolean reentrantLock() {
String value = String.valueOf(Thread.currentThread().getId());
long expireTime = System.currentTimeMillis() + LOCK_EXPIRE + 1;
// 判断是否已经获取锁
if (value.equals(jedis.get(lockKey))) {
lockCount++;
return true;
}
// 获取锁失败,等待其他线程释放锁
while (System.currentTimeMillis() < expireTime) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (jedis.setnx(lockKey, value) == 1) {
jedis.expire(lockKey, LOCK_EXPIRE);
lockCount = 1;
return true;
}
if (value.equals(jedis.get(lockKey))) {
jedis.expire(lockKey, LOCK_EXPIRE);
lockCount = 1;
return true;
}
}
return false;
}
}
```
说明:
1. 使用AtomicInteger记录当前线程持有锁的数量,以便实现重入锁。
2. lock()方法尝试获取锁,如果获取成功,则返回true;如果锁已经被其他线程获取,则等待一段时间后再次尝试获取锁。
3. unlock()方法释放锁,如果当前线程持有的锁数量为1,则直接释放锁;否则减少持有锁的数量。
4. reentrantLock()方法用于实现重入锁,如果当前线程已经持有锁,则只需要增加持有锁的数量即可。
阅读全文