Java try finally race condition?

A lot of Java resource usage examples look like this:

Resource r = openResource(); 
try { 
  // use resource
} finally { 
  r.close();
}

The declaration of r has to be outside of the try-clause to be visible in the finally-clause, but this also makes it look like there's a potential race condition: what if there's a thread interruption right between the openResource()-call and entering the try-clause?

Could that mean that the resource doesn't actually get closed in that scenario?

Or does Java guarantee that the try-finally covers r "fully", despite the syntax looking like it wouldn't?

Or do I have to write:

Resource r = null;  
try { 
  r = openResource();
  // use resource
} finally { 
  if (r != null) r.close();
}

in order to protect against thread interruptions?

Jon Skeet
people
quotationmark

what if there's a thread interruption right between the openResource()-call and entering the try-clause?

Then the thread won't throw an InterruptedException until it hits some blocking call. That can't happen before it gets into the try block, because there aren't any more blocking calls, assuming the method actually returns. From the docs for InterruptedException:

Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity. Occasionally a method may wish to test whether the current thread has been interrupted, and if so, to immediately throw this exception.

Note that even if you do put the acquisition inside the try block, that doesn't really prevent any race condition that would otherwise exist - because you'd be relying on the method or constructor returning in the first place. If an exception can happen after the method/constructor returns, why can't it happen just before it returns, but after the resource has been acquired? If that happens, there's nothing you can call close on...

I'd still recommend using the try-with-resources statement in Java 7, but if you look at the JLS section 14.20.3.1 you'll see that the expansion is like your first piece of code:

The meaning of a basic try-with-resources statement:

try ({VariableModifier} R Identifier = Expression ...)
    Block

is given by the following translation to a local variable declaration and a try-catch-finally statement:

{
    final {VariableModifierNoFinal} R Identifier = Expression;
    Throwable #primaryExc = null;

    try ResourceSpecification_tail
        Block
    catch (Throwable #t) {
        ...
        #primaryExc = #t;
        throw #t;
    } finally {
       ...
    }
}

people

See more on this question at Stackoverflow