/** * Method "tryLockUnrestricted". * * @param key * @return {@code true} if the lock was free and was acquired by the current thread, or the lock * was already held by the current thread; and {@code false} otherwise * @throws InterruptedException * @throws IllegalArgumentException if bean is null * @see java.util.concurrent.locks.ReentrantLock#tryLock() */ public boolean tryLockUnrestricted(final KP key) { checkStopped(); blockOperationIfRequired(); incrementRunningOperations(); boolean tryLockResultBoolean; try { final AtomicBoolean tryLockResult = new AtomicBoolean(); final CyclicBarrier cyclicBarrier = new CyclicBarrier(2); Callable<Boolean> callable = new Callable<Boolean>() { /* * (non-Javadoc) * * @see java.util.concurrent.Callable#call() */ @Override public Boolean call() throws Exception { boolean locked; try { locked = locker.tryLock(key); tryLockResult.set(locked); } finally { // STEP 1 cyclicBarrier.await(); } if (locked) { // STEP 2 cyclicBarrier.await(); return locker.unlock(key); } else { return false; } } }; Future<Boolean> futureTask = threadPool.submit(callable); try { // STEP 1 cyclicBarrier.await(); } catch (Exception e) { throw new RuntimeException(e); } tryLockResultBoolean = tryLockResult.get(); if (tryLockResultBoolean) { LockerValue<KP> lockerValue = locker.getLockerValue(key); Thread callerThreadLocker = Thread.currentThread(); lockerValue.addHandler( new LockerValueHandler(futureTask, cyclicBarrier, callerThreadLocker)); } } finally { decrementRunningOperations(); } return tryLockResultBoolean; }
/** * Method "unlockUnrestricted". Unlock the operations with the provided key. * * <p>To detect incorrect unlocking, this method may return an <code>IllegalStateException</code> * when the lock has been already unlocked or it never been locked. * * @param key * @return true if the key has been found to release the lock; and false otherwise * @throws IllegalStateException * @see java.util.concurrent.locks.ReentrantLock#unlock() */ public boolean unlockUnrestricted(final KP key) { checkStopped(); blockOperationIfRequired(); Boolean resultFuture; incrementRunningOperations(); try { LockerValue<KP> lockerValue = locker.getLockerValue(key); if (lockerValue == null) { throw new IllegalStateException(NOT_ALREADY_LOCKED_MESSAGE + " key=" + key); } LockerValueHandler handler = lockerValue.getHandlerAndRemove(); if (handler == null) { throw new UnsupportedOperationException( "Either you have to use the restricted unlock() method to unlock, or you have to use '*Lock*Unrestricted()' methods to lock !"); } CyclicBarrier barrier = handler.getBarrier(); try { // STEP 2 barrier.await(); } catch (Exception e) { throw new RuntimeException(e); } Future<Boolean> future = handler.getFuture(); if (future.isCancelled()) { return false; } resultFuture = null; try { resultFuture = future.get(); } catch (Exception e) { throw new RuntimeException(e); } } finally { decrementRunningOperations(); } cleanAccordingOperations(); return resultFuture; }
private void waitForRunningOperationsEnded() { blockAllOperations(); boolean breakAtNext = false; while (true) { Collection<LockerValue<KP>> values = locker.getMapKeyLockToValueLock().values(); int waitingThreads = 0; for (LockerValue<KP> lockerValue : values) { waitingThreads += lockerValue.getLock().getQueueLength(); } if (runningOperations.get() - waitingThreads <= 0) { if (breakAtNext) { break; } breakAtNext = true; } else { breakAtNext = false; } try { Thread.sleep(10); } catch (InterruptedException e) { break; } } }
/** * Method "tryLockUnrestricted". * * @param key * @param timeout the time to wait for the lock * @param unit the time unit of the timeout argument * @return true if the lock was free and was acquired by the current thread, or the lock was * already held by the current thread; and false if the waiting time elapsed before the lock * could be acquired * @throws InterruptedException * @throws IllegalArgumentException if bean is null * @see java.util.concurrent.locks.ReentrantLock#tryLock(long, java.util.concurrent.TimeUnit) */ public boolean tryLockUnrestricted(final KP key, final long timeout, final TimeUnit unit) throws InterruptedException { checkStopped(); blockOperationIfRequired(); incrementRunningOperations(); boolean tryLockResultBoolean = false; try { final AtomicBoolean tryLockResult = new AtomicBoolean(); final AtomicReference<InterruptedException> interruptedExceptionFromTryRef = new AtomicReference<InterruptedException>(); final CyclicBarrier cyclicBarrier = new CyclicBarrier(2); Callable<Boolean> callable = new Callable<Boolean>() { /* * (non-Javadoc) * * @see java.util.concurrent.Callable#call() */ @Override public Boolean call() throws Exception { boolean locked = false; try { locked = locker.tryLock(key, timeout, unit); tryLockResult.set(locked); } catch (InterruptedException e) { interruptedExceptionFromTryRef.set(e); return false; } finally { // STEP 1 cyclicBarrier.await(); } if (locked) { // STEP 2 cyclicBarrier.await(); return locker.unlock(key); } else { return false; } } }; Future<Boolean> futureTask = threadPool.submit(callable); try { // STEP 1 cyclicBarrier.await(); } catch (Exception e) { throw new RuntimeException(e); } InterruptedException interruptedExceptionFromTry = interruptedExceptionFromTryRef.get(); if (interruptedExceptionFromTry != null) { throw interruptedExceptionFromTry; } tryLockResultBoolean = tryLockResult.get(); if (tryLockResultBoolean) { LockerValue<KP> lockerValue = locker.getLockerValue(key); Thread threadLocker = Thread.currentThread(); lockerValue.addHandler(new LockerValueHandler(futureTask, cyclicBarrier, threadLocker)); locker.traceStackForDebugging(lockerValue); } } finally { decrementRunningOperations(); } return tryLockResultBoolean; }
/** * Method "lockInterruptiblyUnrestricted". * * @param key * @throws InterruptedException * @see java.util.concurrent.locks.ReentrantLock#lockInterruptibly() */ public void lockInterruptiblyUnrestricted(final KP key) throws InterruptedException { checkStopped(); blockOperationIfRequired(); LockerValue<KP> lockerValue = null; LockerValueHandler handler = null; if (tryLockUnrestricted(key)) { return; } incrementRunningOperations(); /* Test if already locked by the same thread */ lockerValue = locker.getLockerValue(key); if (locker != null) { handler = lockerValue.getHandler(); if (handler != null && Thread.currentThread() == handler.getCallerThreadLocker()) { decrementRunningOperations(); return; } } try { final Thread threadLocker = Thread.currentThread(); final CyclicBarrier cyclicBarrier = new CyclicBarrier(2); final AtomicBoolean hasError = new AtomicBoolean(); Callable<Boolean> callable = new Callable<Boolean>() { /* * (non-Javadoc) * * @see java.util.concurrent.Callable#call() */ @Override public Boolean call() throws Exception { try { locker.lockInterruptibly(key); } catch (Exception e) { hasError.set(true); throw e; } finally { // STEP 1 cyclicBarrier.await(); } // STEP 2 cyclicBarrier.await(); boolean unlocked = locker.unlock(key); return unlocked; } }; Future<Boolean> futureTask = threadPool.submit(callable); try { // STEP 1 cyclicBarrier.await(); } catch (BrokenBarrierException e) { throw new RuntimeException(e); } if (hasError.get()) { try { futureTask.get(); } catch (ExecutionException e) { Throwable cause = e.getCause(); if (cause != null && cause instanceof InterruptedException) { throw (InterruptedException) cause; } else { throw new RuntimeException(e); } } } lockerValue = locker.getLockerValue(key); lockerValue.addHandler(new LockerValueHandler(futureTask, cyclicBarrier, threadLocker)); } finally { decrementRunningOperations(); } }