package org.springblade.common.utils;
|
|
import org.springblade.core.redis.cache.BladeRedis;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.locks.LockSupport;
|
|
@Component
|
public class SpinLockUtil {
|
@Autowired
|
private BladeRedis bladeRedis;
|
|
private static final String LOCK_PREFIX = "thread-safe-lock:";
|
private static final Long DEFAULT_LOCK_TIMEOUT = 6L; // 默认锁超时时间,单位:秒
|
|
|
/**
|
* 尝试获取锁,如果获取失败则自旋等待。
|
*
|
* @param lockKey 锁的键
|
* @return 是否成功获取锁
|
*/
|
public boolean tryLock(String lockKey) {
|
String threadId = Thread.currentThread().getName() + Thread.currentThread().getId(); // 使用线程名和ID作为标识
|
long startTime = System.currentTimeMillis();
|
while (System.currentTimeMillis() - startTime < DEFAULT_LOCK_TIMEOUT * 1000) {
|
if (bladeRedis.getRedisTemplate().opsForValue().setIfAbsent(LOCK_PREFIX + lockKey, threadId,
|
DEFAULT_LOCK_TIMEOUT, TimeUnit.SECONDS)) {
|
return true;
|
}
|
// 短暂休眠,避免高并发下的CPU过度消耗
|
LockSupport.parkNanos(100_000_000L); // 使用LockSupport进行更细粒度的暂停,单位为纳秒
|
}
|
return false;
|
}
|
|
/**
|
* 释放锁,只有加锁的线程才能解锁
|
*
|
* @param lockKey 锁的键
|
* @return 是否成功释放锁
|
*/
|
public boolean unlock(String lockKey) {
|
String threadId = Thread.currentThread().getName() + Thread.currentThread().getId();
|
String currentValue = (String) bladeRedis.getRedisTemplate().opsForValue().get(LOCK_PREFIX + lockKey);
|
if (threadId.equals(currentValue)) {
|
bladeRedis.getRedisTemplate().delete(LOCK_PREFIX + lockKey);
|
return true;
|
}
|
return false; // 如果不是当前线程持有的锁,则返回false,不进行解锁操作
|
}
|
|
}
|