package com.sunyard.util; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; /** * IP锁工具类 - 高并发安全实现 * * 为每个IP地址提供唯一的可重入锁,确保同一IP的操作顺序执行 */ public class IpLockUtils { private static final ConcurrentMap LOCK_MAP = new ConcurrentHashMap<>(); private static final Object CREATION_LOCK = new Object(); /** * 获取IP对应的锁(保证唯一性) * @param ip IP地址 * @return 可重入锁实例 */ public static ReentrantLock getLockForIp(String ip) { ReentrantLock lock = LOCK_MAP.get(ip); if (lock != null) { return lock; } synchronized (CREATION_LOCK) { // 双重检查 lock = LOCK_MAP.get(ip); if (lock == null) { lock = new ReentrantLock(true); // 公平锁 LOCK_MAP.put(ip, lock); } return lock; } } /** * 安全加锁(带超时机制) * @param ip IP地址 * @param timeout 超时时间 * @param unit 时间单位 * @return 是否成功获取锁 * @throws InterruptedException */ public static boolean lockWithTimeout(String ip, long timeout, TimeUnit unit) throws InterruptedException { ReentrantLock lock = getLockForIp(ip); return lock.tryLock(timeout, unit); } /** * 解锁指定IP的锁 * @param ip IP地址 */ public static void unlockForIp(String ip) { ReentrantLock lock = LOCK_MAP.get(ip); if (lock != null && lock.isHeldByCurrentThread()) { lock.unlock(); } } /** * 清理未使用的锁(可选) */ public static void cleanupUnusedLocks() { LOCK_MAP.entrySet().removeIf(entry -> !entry.getValue().isLocked() && entry.getValue().getQueueLength() == 0 ); } /** * 获取当前锁数量 */ public static int getLockCount() { return LOCK_MAP.size(); } /** * 获取IP锁状态 * @param ip IP地址 * @return 锁状态字符串 */ public static String getLockStatus(String ip) { ReentrantLock lock = LOCK_MAP.get(ip); if (lock == null) { return "No lock exists"; } return String.format("Locked: %s, Queue: %d, HoldCount: %d", lock.isLocked(), lock.getQueueLength(), lock.getHoldCount()); } /** * 重置所有锁 */ public static void reset() { synchronized (CREATION_LOCK) { LOCK_MAP.clear(); } } }