0

我写了以下wrapepr:

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

我不想在每种方法中创建包装器。

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

4

3 回答 3

1

你的设计过于复杂了。如果您AutoCloseableLockWrapper有意公开底层支持的所有操作,那么制作它并为每个方法添加委托方法Lock是没有意义的。您可以简单地进行引用以允许使用它,或者完全不使用它,因为创建包装器的代码已经引用了.privateLockLockpublicLock

您要做的就是支持单个操作,unlock应该被视为AutoCloseable.

Java 8 解决方案可能看起来像

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
}

如果您担心实例创建(通常这不是问题),您可以重用AutoCloseables:

AutoUnlock reusable=lock::unlock;
// …
lock.lock();
try(AutoUnlock u=reusable) {
    // critical code
}
// …
lock.lock();
try(AutoUnlock u=reusable) {
    // critical code
}

对我来说,它看起来不太清楚,因为lock();andtry语句在语法上不是耦合的,并且可能会被意外分开。但是如果锁有一个非本地范围,你可以通过创建一个实用方法来解决这个问题:

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 代码中并不难。

于 2015-09-29T18:20:53.860 回答
1

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

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

我看到上面的注释已经发布在你贡献了 wrapper 的 Q&A 页面上。页面已经有很好的内容;我建议好好学习。

于 2015-08-06T11:26:17.867 回答
0

我宁愿只创建一个新锁(而不是锁的包装器):

public class AutoReentrantLock implements AutoCloseable {
  private final ReentrantLock lock = new ReentrantLock();

  public AutoReentrantLock lock() {
    lock.lock();

    return this;
  }

  public void earlyUnlock() {
    lock.unlock();
  }

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

像这样使用:

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.
}
于 2019-04-02T08:31:06.303 回答