boolean readLockedAtEntry = releaseReadLock();
boolean readLockedAtEntry = releaseReadLock();
/** * Acquires the exclusive write lock before invoking the Invokable. The code will be executed exclusively, no other * reader or writer threads will exist (they will be blocked waiting for the lock). If the current thread has a read * lock, it is released before attempting to acquire the write lock, and re-acquired after the write lock is * released. Note that in that short window, between releasing the read lock and acquiring the write lock, it is * entirely possible that some other thread will sneak in and do some work, so the {@link Invokable} object should * be prepared for cases where the state has changed slightly, despite holding the read lock. This usually manifests * as race conditions where either a) some parallel unrelated bit of work has occured or b) duplicate work has * occured. The latter is only problematic if the operation is very expensive. * * @param <T> * @param invokable */ public <T> T withWrite(Invokable<T> invokable) { boolean readLockedAtEntry = releaseReadLock(); lock.writeLock().lock(); try { return invokable.invoke(); } finally { lock.writeLock().unlock(); restoreReadLock(readLockedAtEntry); } }
/** * Acquires the exclusive write lock before invoking the Invokable. The code will be executed exclusively, no other * reader or writer threads will exist (they will be blocked waiting for the lock). If the current thread has a read * lock, it is released before attempting to acquire the write lock, and re-acquired after the write lock is * released. Note that in that short window, between releasing the read lock and acquiring the write lock, it is * entirely possible that some other thread will sneak in and do some work, so the {@link Invokable} object should * be prepared for cases where the state has changed slightly, despite holding the read lock. This usually manifests * as race conditions where either a) some parallel unrelated bit of work has occured or b) duplicate work has * occured. The latter is only problematic if the operation is very expensive. * * @param <T> * @param invokable */ public <T> T withWrite(Invokable<T> invokable) { boolean readLockedAtEntry = releaseReadLock(); lock.writeLock().lock(); try { return invokable.invoke(); } finally { lock.writeLock().unlock(); restoreReadLock(readLockedAtEntry); } }