try-with-resources is another option ( in addition to Andy's answer ) but Lock
is not AutoCloseable
.
So you can write a wrappper as explained here in another SO question and here then you can use try-with-resource with this wrapper.
Probably, its not worth the effort if you are not planning to use similar construct at multiple places in your application.
EDIT : Elaborating answer to address Sotirios Delimanolis's concerns .
In my opinion , OP wants to throw a RuntimeException
if lock can't be acquired and is confused about closing of lock in finally
block since it might throw IllegalMonitorStateException
if lock is not already held by thread.
Using Lock
gives you flexibility to unlock
at any place that programmer wants ( and not necessarily at the end of try block or at the end of method ) & that flexibility is missing in synchronized
keyword but as per code snippet of OP, it seems he will unlock just after finishing immediate try
block so AutoCloseable
makes sense.
Below code addresses both concerns ,
Wrapper class
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class CloseableReentrantLock extends ReentrantLock implements
AutoCloseable {
private static final long serialVersionUID = 1L;
public CloseableReentrantLock timedLock() throws InterruptedException{
if(this.tryLock(120, TimeUnit.SECONDS))
return this;
else
throw new RuntimeException("timeout");
}
@Override
public void close() throws Exception {
this.unlock();
}
}
Client
try(CloseableReentrantLock lock = new CloseableReentrantLock().timedLock())
{
//do stuff here
}
Lock Acquired Scenario : Nothing special happens , close
method is called after try-with-resource block and lock is unlocked. This is more or less the way synchronized
block works but you can't get a waiting time option with synchronized
but the finally
code cluttering & chances that programmer will miss to code unlock
& finally
are not there with syncronized
and so is the case with Closeable
wrapper.
Lock can't be Acquired : In this scenario, since resource is not successfully acquired with in try-with-resource and try-with-resource itself throws Exception, close
will not be called on this resource and so IllegalMonitorStateException
will not be there.
Refer this question and accepted answer to understand more for exceptions from within try-with-resource itself.
This sample code illustrates it further,
public class TryResource implements AutoCloseable{
public TryResource getResource(boolean isException) throws Exception{
if ( isException) throw new Exception("Exception from closeable getResource method");
else return this;
}
public void doSomething() throws Exception {
System.out.println("In doSomething method");
}
@Override
public void close() throws Exception {
System.out.println("In close method");
throw new Exception("Exception from closeable close method");
}
}
and client,
public class TryResourceClient {
public static void main(String[] args) throws Exception {
try (TryResource resource = new TryResource().getResource(true)){
resource.doSomething();
}
}
}