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();
}
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.
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.
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.
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.
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();
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With