Greg
Greg

Reputation: 2049

Threads - Why a Lock has to be followed by try and finally

A Lock is always followed by a try/finally block, why?

ReentrantReadWriteLock readWriteLockBitmap = new ReentrantReadWriteLock();
Lock read = readWriteLockBitmap.readLock();
Lock write = readWriteLockBitmap.writeLock();
int shared = 0;

public void function1(){
    read.lock();
    try{
        //reading shared int
    }
    finally{
        read.unlock();
    }
}

public void function 2(){
    write.lock();
    try{
        //modify shared int
    }
    finally{
        write.unlock();
    }
}

Why having this try/finally block and not simply writing the code as follows:

ReentrantReadWriteLock readWriteLockBitmap = new ReentrantReadWriteLock();
Lock read = readWriteLockBitmap.readLock();
Lock write = readWriteLockBitmap.writeLock();
int shared = 0;

public void function1(){
    read.lock();
    //reading shared int
    read.unlock();
}

public void function 2(){
    write.lock();
    //modify shared int
    write.unlock();
}

Upvotes: 7

Views: 7575

Answers (6)

Ryan Stewart
Ryan Stewart

Reputation: 128899

So that something like this doesn't happen:

private static ReentrantReadWriteLock readWriteLockBitmap = new ReentrantReadWriteLock();
private static Lock read = readWriteLockBitmap.readLock();
private static Lock write = readWriteLockBitmap.writeLock();
private static int shared = 0;

public static void function1() {
    read.lock();
    somethingThatMightThrowAnException();
    read.unlock();
}

private static void somethingThatMightThrowAnException() {
    throw new RuntimeException("I'm a bad man.");
}

public static void function2() {
    write.lock();
    //modify shared int
    write.unlock();
}

public static void main(String[] args) {
    try {
        function1();
    } catch (Exception e) {
        System.out.println("Got an exception, but so what?");
    }
    function2();
}

Upvotes: 6

jdmichal
jdmichal

Reputation: 11162

Because a try/finally block is the only way to guarantee that a segment of code is executed after another completes.

You ask why not do this:

public void function1(){
    read.lock();
    this.getSharedInt();
    read.unlock();
}

What happens when this.getSharedInt() throws an exception? Then your read.unlock() line will not be executed, causing program deadlock. Sure, it may be 100% certified to not throw an exception right now, but what happens when you refactor to store that shared int in a file or database?

Finally, don't forget that try/finally also accounts for errors, which can be thrown by the runtime at almost any line in a program, even if the function is guaranteed to not throw any exceptions.

Note that this code would also work, but it swallows the exception. Using finally instead allows the exception to propagate normally, while still unlocking under all conditions.

public void function2(){
    read.lock();
    try {
        this.getSharedInt();
    } catch(Throwable t) {}
    read.unlock();
}

Upvotes: 11

Gilead
Gilead

Reputation: 1526

http://www.google.co.uk/#sclient=psy&hl=en&q=java+Why+a+Lock+has+to+be+followed+by+try+and+finally+%3F

First hit is: http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/locks/Lock.html

Quoting the key part:

In most cases, the following idiom should be used:

 Lock l = ...; 
 l.lock();
 try {
     // access the resource protected by this lock
 } finally {
     l.unlock();
 }  

When locking and unlocking occur in different scopes, care must be taken to ensure that all code that is executed while the lock is held is protected by try-finally or try-catch to ensure that the lock is released when necessary.

Upvotes: 1

Marvo
Marvo

Reputation: 18143

The issue isn't that you need the try block. The point is to ensure that if you're app throws an exception of any sort that the unlock is still called. Otherwise, the lock would stay locked.

Upvotes: 3

MByD
MByD

Reputation: 137382

To make sure that whatever happens, even if an exception is thrown, you will still unlock the locked stream before leaving the method.

Upvotes: 2

Paul Bellora
Paul Bellora

Reputation: 55223

In case anything goes wrong (Exception being thrown etc.) you want to make sure the lock is released no matter what. It's just standard practice, even though in this case may technically be unnecessary.

Upvotes: 6

Related Questions