导入pom
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
@Configuration
public class LockConfig {
@Bean
public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {
// 第一个参数redisConnectionFactory
// 第二个参数registryKey,分布式锁前缀,设置为项目名称会好些
// 该构造方法对应的分布式锁,默认有效期是60秒.可以自定义
return new RedisLockRegistry(redisConnectionFactory, "xxx", 15000L);
}
}
public class LockUtil {
private static volatile RedisLockRegistry redisLockRegistry;
private static RedisLockRegistry redisLockRegistry() {
if (redisLockRegistry == null) {
synchronized (LockUtil.class) {
if (redisLockRegistry == null) {
redisLockRegistry = SpringUtils.getBean(RedisLockRegistry.class);
}
}
}
return redisLockRegistry;
}
public static <T> T lock(String key, Supplier<T> supplier, long timeout, TimeUnit unit) {
Lock lock = null;
boolean locked = false;
try {
lock = redisLockRegistry().obtain(key);
// 尝试加锁
if ((locked = lock.tryLock(timeout, unit))) {
return supplier.get();
} else {
log.warn("try Lock fail key {} ", key);
throw new AppException(AppErrorEnum.DEFAULT_ERROR);
}
} catch (Exception e) {
log.error("tryLock ", e);
throw new AppException(AppErrorEnum.DEFAULT_ERROR);
} finally {
if (Objects.nonNull(lock) && locked) {
try {
lock.unlock();
} catch (Exception e) {
log.error("unlock error ", e);
}
}
}
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = AppApplication.class)
public class LockTest{
protected final Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
RedisLockRegistry redisLockRegistry;
public void testLock() {
List<CompletableFuture> futures = Lists.newArrayList();
String redisKey = "key";
for (int i = 0; i < 10; i++) {
String finalI = i + "";
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(
() -> {
LockUtil.lock(redisKey, () -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.info("exec task time {} , value {}", (System.currentTimeMillis()), finalI);
return finalI;
}, 40, TimeUnit.SECONDS);
});
futures.add(completableFuture);
}
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
}
}
总结
-
没有看门狗机制,不会自动续期,设置默认过期时间后,就剔除redis,key了。
-
不支持红锁。
-
锁的持有者释放锁后,有竞争线程在等待锁,最多需要自旋100ms才能检测到锁的释放,没有主动唤醒机制。