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();}