令人惊讶的是,这个问题没有令人满意的答案。LockCloseable的安全使用将类似于
try (LockCloseable lockCloseable = LockCloseable.lock(lock)) {
    doSomethingUnderLock();
} // automatic release或者使用@lombok.Cleanup
{
    @Cleanup LockCloseable lockCloseable = LockCloseable.lock(lock)
    doSomethingUnderLock();
} // automatic release when the scope is left所有答案要么创建一个新的锁(无意义),要么当锁定时返回一个现有对象(危险)或返回空(无法用try-with资源)。
所以我试试看:
@RequiredArgsConstructor(access=AccessLevel.PRIVATE)
public final class MgLockCloseable implements AutoCloseable {
    public static MgLockCloseable tryLock(Lock lock) {
        return new MgLockCloseable(lock.tryLock() ? lock : null);
    }
    public static MgLockCloseable lock(Lock lock) {
        lock.lock();
        return new MgLockCloseable(lock);
    }
    @Override public void close() {
        if (isLocked()) {
            lock.unlock();
        }
    }
    public boolean isLocked() {
        return lock != null;
    }
    @Nullable private final Lock lock;
}备注:
RequiredArgsConstructor来自lombok,完全按照名字的意思来做。AutoCloseable,因为收尾不是幂等的。发布于 2017-03-20 12:28:14
如果在循环中获得的话,MgLockCloseable.tryLock()是不实用的。人们传统上是这样做的:
while (!lock.tryLock()) {
    sleep();
}
try {
    // do locked stuff
} finally {
    lock.unlock();
}这是使用MgLockClosable进行此操作所必需的:
boolean processed = false;
while (!processed) {
    try (AutoClosable closable = MgLockClosable.tryLock()) {
        if (closable.isLocked()) {
            processed = true;
            // do locked stuff
        } else {
            sleep();
        }
    }
}来自AutoClosable.close()的javadoc:
强烈鼓励该接口的实现者使其密切的方法成为幂等的。
很容易使close()实现幂等,并且在某些场景中很有用:
try (MgLockClosable writeLocked = MgLockClosable.lock(getLock().writeLock()) {
    try (MgLockClosable ignored = MgLockClosable.lock(getLock().readLock()) {
        // do write lock related stuff
        writeLocked.close();
        // do write lock unrelated stuff (potentially slow)
    }
}代码演示了读/写锁降级。将逻辑分成两个块,一个需要写锁,另一个需要读锁,具有更好的并发性。同时,代码仍然保存,因为在任何情况下都会释放这两个锁。
我会在lock()中交换这两行。如果构造函数抛出(由于任何原因,我们目前还不知道),那么锁将永远不会被解锁。另一方面,如果您交换行:如果构造函数抛出,则不会获得锁。如果Lock.lock()抛出,则永远不会返回MgLockCloseable实例。
https://codereview.stackexchange.com/questions/129068
复制相似问题