/** * @param key Key to lock. * @return Sync object that should be passed to {@link #unlock(Object, Object)} method. */ public <T> Object lock(T key) { assert key != null; boolean interrupted = false; Sync t = new Sync(); try { while (true) { Sync old = locks.putIfAbsent(key, t); if (old != null) { while (true) { try { old.await(); break; } catch (InterruptedException ignored) { interrupted = true; } } } else return t; } } finally { if (interrupted) Thread.currentThread().interrupt(); } }
/** * @param key Key to lock. * @return Sync object that should be passed to {@link #unlock(Object, Object)} method. * @throws InterruptedException If interrupted while acquiring lock. */ public <T> Object lockInterruptibly(T key) throws InterruptedException { assert key != null; Sync t = new Sync(); while (true) { Sync old = locks.putIfAbsent(key, t); if (old != null) old.await(); else return t; } }
/** * @param key Key. * @param sync Sync that got from {@link #lockInterruptibly(Object)} call. */ public <T> void unlock(T key, Object sync) { if (!locks.remove(key, sync)) throw new IllegalStateException("Lock has not been acquired for key: " + key); ((Sync) sync).finish(); }