/**
* 单机、粒度为 key 的可重入锁。* 同一个 key、同一时刻,只能一个线程执行
* @see java.util.concurrent.locks.Lock
* @see java.util.concurrent.locks.ReentrantLock
*/
public interface KeyLock<T> {
/**
* 加锁
*/
void lock(T key);
boolean tryLock(T key, long time, TimeUnit unit);
/**
* 解锁
*/
void unlock(T key);
}
@Slf4j
public class DefaultKeyLock<T> implements KeyLock<T> {private final Map<T, ReentrantLock> lockMap = new ConcurrentHashMap<>();
@Override
public void lock(T key) {Preconditions.checkArgument(Objects.nonNull(key), "key can not be null");
ReentrantLock lock = lockMap.computeIfAbsent(key, k -> new ReentrantLock());
lock.lock();}
@SneakyThrows(value = {InterruptedException.class})
@Override
public boolean tryLock(T key, long time, TimeUnit unit) {Preconditions.checkArgument(Objects.nonNull(key), "key can not be null");
ReentrantLock lock = lockMap.computeIfAbsent(key, k -> new ReentrantLock());
boolean flag = lock.tryLock(time, unit);
if (flag) {log.info("get the lock {} success", key);
} else {log.info("get the lock {} failure", key);
}
return flag;
}
@Override
public void unlock(T key) {Preconditions.checkArgument(Objects.nonNull(key), "key can not be null");
ReentrantLock lock = lockMap.get(key);
if (Objects.isNull(lock)) {throw new IllegalArgumentException("key:" + key + "does not own a lock");
}
if (!lock.isHeldByCurrentThread()) {throw new IllegalStateException("current thread does not oww a lock,key:" + key);
}
lock.unlock();
log.info("release the lock {} success", key);
}
}