Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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();
}
like image 983
Greg Avatar asked Aug 05 '11 00:08

Greg


People also ask

Why lock is used in threading?

A lock allows you to force multiple threads to access a resource one at a time, rather than all of them trying to access the resource simultaneously. As you note, usually you do want threads to execute simultaneously.

Why must a thread be holding a lock to wait on a condition variable?

The lock is used to enforce mutual exclusion. The condition variables are used as wait queues so that other threads can sleep while the lock is held. Thus condition variables make it so that if a thread can safely go to sleep and be guaranteed that when they wake up they will have control of the lock again.

How do locks work with threads?

A thread that tries to acquire a lock that is held by another thread spins for a short while. While it spins, the thread continuously checks whether the lock it needs is still held by the other thread. This is the default behavior on multiple-CPU systems. Such a lock is called a thin lock.

What does it mean for a thread to be locked?

The LOCK THREAD statement ensures that no other thread executes. This condition remains in effect until the thread is unlocked (with UNLOCK THREAD) or the thread terminates.


2 Answers

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();
}
like image 85
jdmichal Avatar answered Nov 15 '22 08:11

jdmichal


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.

like image 36
Paul Bellora Avatar answered Nov 15 '22 07:11

Paul Bellora