Are Locks auto-closeable? That is, instead of:

Lock someLock = new ReentrantLock();
someLock.lock();
try
{
    // ...
}
finally
{
    someLock.unlock();
}

...can I say:

try (Lock someLock = new ReentrantLock())
{
    someLock.lock();
    // ...
}

...in Java 7?


I was looking into doing this myself and did something like this:

public class CloseableReentrantLock extends ReentrantLock implements AutoCloseable { 
   public CloseableReentrantLock open() { 
      this.lock();
      return this;
   }

   @Override
   public void close() {
      this.unlock();
   }
}

and then this as usage for the class:

public class MyClass {
   private final CloseableReentrantLock lock = new CloseableReentrantLock();

   public void myMethod() {
      try(CloseableReentrantLock closeableLock = lock.open()) {
         // locked stuff
      }
   }
}

No, neither the Lock interface (nor the ReentrantLock class) implement the AutoCloseable interface, which is required for use with the new try-with-resource syntax.

If you wanted to get this to work, you could write a simple wrapper:

public class LockWrapper implements AutoCloseable
{
    private final Lock _lock;
    public LockWrapper(Lock l) {
       this._lock = l;
    }

    public void lock() {
        this._lock.lock();
    }

    public void close() {
        this._lock.unlock();
    }
}

Now you can write code like this:

try (LockWrapper someLock = new LockWrapper(new ReentrantLock()))
{
    someLock.lock();
    // ...
}

I think you're better off sticking with the old syntax, though. It's safer to have your locking logic fully visible.


The general-purpose ReentrantLock neither implements nor provides anything that implements the AutoCloseable interface necessary for a try-with-resources statement. The concept isn't completely foreign to the Java API though, as FileChannel.lock() offers this functionality.

The answers given so far share solutions that have some issues, such as creating an unnecessary object on each lock call, exposing an error-prone API or risk failing after the lock is acquired but before the try-finally is entered.

Java 7 solution:

public interface ResourceLock extends AutoCloseable {

    /**
     * Unlocking doesn't throw any checked exception.
     */
    @Override
    void close();
}

public class CloseableReentrantLock extends ReentrantLock {

    private final ResourceLock unlocker = new ResourceLock() {
        @Override
        public void close() {
            CloseableReentrantLock.this.unlock();
        }
    };

    /**
     * @return an {@link AutoCloseable} once the lock has been acquired.
     */
    public ResourceLock lockAsResource() {
        lock();
        return unlocker;
    }
}

Leaner Java 8 solution using a lambda:

public class CloseableReentrantLock extends ReentrantLock {

    /**
     * @return an {@link AutoCloseable} once the lock has been acquired.
     */
    public ResourceLock lockAsResource() {
        lock();
        return this::unlock;
    }
}

Demonstration:

public static void main(String[] args) {
    CloseableReentrantLock lock = new CloseableReentrantLock();

    try (ResourceLock ignored = lock.lockAsResource()) {
        try (ResourceLock ignored2 = lock.lockAsResource()) {
            System.out.println(lock.getHoldCount());  // 2
        }
    }
    System.out.println(lock.getHoldCount());  // 0
}