![]() |
COMPLETE SELF-HEALING DEADLOCK IMPLEMENTATION GUIDE - Printable Version +- PlayKuro Community (https://forum.playkuro.com) +-- Forum: Kuro Forums (https://forum.playkuro.com/forumdisplay.php?fid=1) +--- Forum: Server Guides (https://forum.playkuro.com/forumdisplay.php?fid=14) +--- Thread: COMPLETE SELF-HEALING DEADLOCK IMPLEMENTATION GUIDE (/showthread.php?tid=47) |
COMPLETE SELF-HEALING DEADLOCK IMPLEMENTATION GUIDE - Kuro - 08-02-2025 SELF-HEALING DEADLOCK IMPLEMENTATION GUIDE OVERVIEW A comprehensive self-healing deadlock system for Java applications with automatic detection and resolution. Components: - DeadlockResolver - Force-releases locks using reflection - LockManager - Timeout-based acquisition - ThreadMonitor - Health monitoring - SelfHealingTimerManager - Auto-recovering threads - Database retry patterns DEADLOCK RESOLVER public class DeadlockResolver { private static final DeadlockResolver instance = new DeadlockResolver(); private final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); private final ConcurrentHashMap<Long, Character> threadCharacterMap = new ConcurrentHashMap<>(); private static final String[] LOCK_FIELD_NAMES = { "chrLock", "effLock", "prtLock", "cpnLock", "petLock", "evtLock" }; public boolean resolveDeadlocks() { long[] deadlockedThreadIds = threadMXBean.findDeadlockedThreads(); if (deadlockedThreadIds == null) return false; boolean resolved = false; for (long threadId : deadlockedThreadIds) { Character chr = threadCharacterMap.get(threadId); if (chr != null && forceReleaseCharacterLocks(chr)) { resolved = true; } } return resolved; } private boolean forceReleaseCharacterLocks(Character character) { boolean success = false; try { Class<?> chrClass = character.getClass(); for (String fieldName : LOCK_FIELD_NAMES) { Field lockField = chrClass.getDeclaredField(fieldName); lockField.setAccessible(true); Object lock = lockField.get(character); if (lock instanceof ReentrantLock) { ReentrantLock reentrantLock = (ReentrantLock) lock; if (reentrantLock.isLocked() && reentrantLock.isHeldByCurrentThread()) { int holdCount = reentrantLock.getHoldCount(); for (int i = 0; i < holdCount; i++) { reentrantLock.unlock(); } success = true; } } } } catch (Exception e) { log.error("Error releasing locks", e); } return success; } public static boolean tryLockWithTimeout(Lock lock, long timeout, TimeUnit unit) { try { boolean acquired = lock.tryLock(timeout, unit); if (!acquired && getInstance().hasDeadlock()) { getInstance().resolveDeadlocks(); acquired = lock.tryLock(1, TimeUnit.SECONDS); } return acquired; } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; } } } THREAD MONITOR public class ThreadMonitor { private static final ThreadMonitor instance = new ThreadMonitor(); private final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); private ThreadMonitor() { ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); executor.scheduleWithFixedDelay(this::checkForDeadlocks, 30, 30, TimeUnit.SECONDS); } public void checkForDeadlocks() { long[] deadlockedThreadIds = threadMXBean.findDeadlockedThreads(); if (deadlockedThreadIds != null && deadlockedThreadIds.length > 0) { log.error("DEADLOCK DETECTED! {} threads", deadlockedThreadIds.length); DeadlockResolver.getInstance().resolveDeadlocks(); } } } SELF-HEALING TIMER public class SelfHealingTimerManager { private volatile ScheduledThreadPoolExecutor ses; private final Map<String, CriticalTask> criticalTasks = new ConcurrentHashMap<>(); private void handleThreadPoolFailure() { log.error("Thread pool failed! Starting recovery..."); if (ses != null) ses.shutdownNow(); createThreadPool(); reRegisterCriticalTasks(); log.info("Recovery completed"); } private void reRegisterCriticalTasks() { for (Map.Entry<String, CriticalTask> entry : criticalTasks.entrySet()) { CriticalTask task = entry.getValue(); task.future = ses.scheduleAtFixedRate( wrapWithErrorHandling(task.runnable), task.initialDelay, task.period, task.unit ); } } } DATABASE RETRY public class DatabaseRetryHelper { private static final int MAX_RETRIES = 3; public static <T> T executeWithRetry(Function<Connection, T> operation, T defaultValue) { for (int i = 0; i < MAX_RETRIES; i++) { try (Connection con = DatabaseConnection.getConnection()) { return operation.apply(con); } catch (SQLException e) { if (!isRetryableException(e) || i == MAX_RETRIES - 1) { return defaultValue; } try { Thread.sleep(100 * (i + 1)); } catch (InterruptedException ie) {} } } return defaultValue; } } LOCK ORDERING public class Character { // CRITICAL: Always acquire in order: prtLock → effLock → chrLock private final ReentrantLock prtLock = new ReentrantLock(true); private final ReentrantLock effLock = new ReentrantLock(true); private final ReentrantLock chrLock = new ReentrantLock(true); public void recalcLocalStats() { Lock[] locks = {prtLock, effLock, chrLock}; if (!DeadlockResolver.tryLockMultipleWithTimeout(locks, 5, TimeUnit.SECONDS)) { log.error("Failed to acquire locks"); return; } try { performStatCalculation(); } finally { chrLock.unlock(); effLock.unlock(); prtLock.unlock(); } } } HIKARICP CONFIG HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://localhost:3306/cosmic"); config.setMaximumPoolSize(130); config.setConnectionTimeout(30000); config.setLeakDetectionThreshold(60000); SERVER INTEGRATION public class Server { private final DeadlockResolver deadlockResolver = DeadlockResolver.getInstance(); private final ThreadMonitor threadMonitor = ThreadMonitor.getInstance(); private final SelfHealingTimerManager timerManager = new SelfHealingTimerManager(); public Server() { timerManager.registerCriticalTask( "DeadlockDetection", this::checkForDeadlocks, 30, 30, TimeUnit.SECONDS ); } } KEY FEATURES 1. Automatic deadlock detection via ThreadMXBean 2. Force-release locks using reflection 3. Self-healing thread pools 4. Database retry with exponential backoff 5. Lock ordering convention prevents deadlocks Battle-tested in production KuroMS! |