Java 如何使用自动关闭的锁包装器?

Java 如何使用自动关闭的锁包装器?,java,concurrency,try-with-resources,autocloseable,Java,Concurrency,Try With Resources,Autocloseable,我写了以下文章: public class AutoCloseableLockWrapper implements AutoCloseable, Lock{ private final Lock lock; public AutoCloseableLockWrapper(Lock l) { this.lock = l; } @Override public void lock() { this.lock.lock();

我写了以下文章:

public class AutoCloseableLockWrapper implements AutoCloseable, Lock{
    private final Lock lock;
    public AutoCloseableLockWrapper(Lock l) {
        this.lock = l;
    }
    @Override
    public void lock() {
        this.lock.lock();
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        lock.lockInterruptibly();
    }

    @Override
    public boolean tryLock() {
        return lock.tryLock();
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return lock.tryLock(time,unit);
    }

    @Override
    public void unlock() {
        lock.unlock();
    }

    @Override
    public Condition newCondition() {
        return lock.newCondition();
    }
    @Override
    public void close() {
        this.lock.unlock();
    }
} 
在我的代码中,我是这样使用它的:

public class ReadWriteMap implements Map {

    private HashMap map = new HashMap();
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private Lock readLock = readWriteLock.readLock();
    private Lock writeLock = readWriteLock.writeLock();

    @Override
    public int size() {
        try (AutoCloseableLockWrapper autoCloseableLockWrapper = new AutoCloseableLockWrapper(readLock)) {
            autoCloseableLockWrapper.lock();
            return map.size();
        }

    }

    @Override
    public boolean isEmpty() {
        try (AutoCloseableLockWrapper autoCloseableLockWrapper = new AutoCloseableLockWrapper(readLock)) {
            autoCloseableLockWrapper.lock();
            return map.isEmpty();
        }
    }

    @Override
    public boolean containsKey(Object key) {
        try (AutoCloseableLockWrapper autoCloseableLockWrapper = new AutoCloseableLockWrapper(readLock)) {
            autoCloseableLockWrapper.lock();
            return map.containsKey(key);
        }
    }
    ...
}
private AutoReentrantLock consistencyLock = new AutoReentrantLock();

try(AutoReentrantLock lock = consistencyLock.lock()) {
  // other code
}
我不想在每个方法中创建包装器


有没有办法组合单个包装器并尝试使用资源?

您可以使用一个工厂方法返回一个单例。没有什么强迫您使用构造函数

顺便说一句,您不应该在try块内调用
lock
。这应该已经发生在“获取资源”阶段(在您当前设计中的构造函数中,在我的提案中的工厂方法中)


我看到上面的说明已经贴在了网站上。页面已经有很好的内容;我建议好好研究一下。

你的设计太复杂了。如果您的
AutoCloseableLockWrapper
故意公开底层
Lock
支持的所有操作,那么将其设置为私有
并为每个
Lock
的方法添加委派方法是没有意义的。您可以简单地将
引用
公开
以允许使用它,或者完全关闭它,因为创建包装的代码已经引用了

您只需支持一个操作,
unlock
,该操作应被视为可自动关闭

Java8解决方案可能看起来像

import java.util.concurrent.locks.Lock;

public interface AutoUnlock extends AutoCloseable {
    public static AutoUnlock lock(Lock lock) {
        lock.lock();
        return lock::unlock;
    }

    @Override
    public void close(); // no checked exceptions
}
它可以像这样使用:

Lock lock=…
// …
try(AutoUnlock u=AutoUnlock.lock(lock)) {
    // critical code
}
// …
try(AutoUnlock u=AutoUnlock.lock(lock)) {
    // critical code
}
如果您担心实例创建(通常这不是问题),您可以重新使用
AutoCloseable
s:

AutoUnlock reusable=lock::unlock;
// …
lock.lock();
try(AutoUnlock u=reusable) {
    // critical code
}
// …
lock.lock();
try(AutoUnlock u=reusable) {
    // critical code
}
在我看来,由于
lock()
try
语句在语法上是不耦合的,可能会意外地分开。但如果锁具有非局部作用域,则可以通过创建实用程序方法来解决此问题:

final Lock lockInstance; // this field name is to prevent confusion with the lock() method
final AutoUnlock reusable;

YourConstructor(Lock lock) {// you may get the Lock as a parameter
    lockInstance=lock; // or create one here, right in the constructor
    reusable=lockInstance::unlock;
}

AutoUnlock lock() {
    lockInstance.lock();
    return reusable;
}
void doSomething() {
    // …
    try(AutoUnlock u=lock()) {
        // critical code
    }
    // …
    try(AutoUnlock u=lock()) {
        // critical code
    }
}

我认为,如果需要的话,将此逻辑向后移植到Java 7代码中并不太难。

我更喜欢只创建一个新锁(而不是锁的包装器):

这样使用:

public class ReadWriteMap implements Map {

    private HashMap map = new HashMap();
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private Lock readLock = readWriteLock.readLock();
    private Lock writeLock = readWriteLock.writeLock();

    @Override
    public int size() {
        try (AutoCloseableLockWrapper autoCloseableLockWrapper = new AutoCloseableLockWrapper(readLock)) {
            autoCloseableLockWrapper.lock();
            return map.size();
        }

    }

    @Override
    public boolean isEmpty() {
        try (AutoCloseableLockWrapper autoCloseableLockWrapper = new AutoCloseableLockWrapper(readLock)) {
            autoCloseableLockWrapper.lock();
            return map.isEmpty();
        }
    }

    @Override
    public boolean containsKey(Object key) {
        try (AutoCloseableLockWrapper autoCloseableLockWrapper = new AutoCloseableLockWrapper(readLock)) {
            autoCloseableLockWrapper.lock();
            return map.containsKey(key);
        }
    }
    ...
}
private AutoReentrantLock consistencyLock = new AutoReentrantLock();

try(AutoReentrantLock lock = consistencyLock.lock()) {
  // other code
}
或者一个更复杂的用例,您可以中途解锁:

private AutoReentrantLock consistencyLock = new AutoReentrantLock();

try(AutoReentrantLock lock = consistencyLock.lock()) {
  // Place code here that gathers information (while under lock)        
  // but may exit early or throw exceptions

  lock.earlyUnlock();

  // ... followed by code that is slow that acts upon above gathered information.
}
无法编写AutoCloseableLockWrapper AutoCloseableLockWrapper=新的AutoCloseableLockWrapper(readLock)的问题;try(autoCloseableLockWrapper){autoCloseableLockWrapper.lock();return map.size();}