Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding lock scope

From this link, I understand "Since the lock() and unlock() method calls are explicit, we can move them anywhere, establishing any lock scope, from a single line of code to a scope that spans multiple methods"

So what I understand from the above statement is

public class Test {
    Lock l = new ReentrantLock();

    void myMethod1() {
        l.lock();
        // Do my stuff here
    }

    void myMethod2() {
        // Do more stuff here
        l.unlock();
    }
}

So basically 1 can call method1 and method2 in sequence and assume the call is thread safe.

I am not sure if it's true as said above.

What if somebody just calls method2 when i am already executing method1/method2 pair? Doesn't it complicate things.

I think a lock should be acquired and released in the function itself, before the control is returned from the function. Is my understanding correct?

like image 380
S Kr Avatar asked Jul 14 '15 11:07

S Kr


2 Answers

Answer to first question:

What if somebody just calls method2 when i am already executing method1/method2 pair? Doesn't it complicate things.

Suppose another thread calls the unlock() method on the ReentrantLock object then IllegalMonitorStateException would be thrown. Because the thread is not acquiring the lock and when it tries to unlock then it get exception.
It will not have any effect on execution or locking of first thread which is acquiring the lock.

  • Same thread:

    • Lock: If same thread which is acquiring the lock again tries to acquire the lock then lock counter increments.
    • Unlock: If same thread which is acquiring the lock tries to unlock then lock counter decrements and as soon as lock counter becomes 0, thread releases the lock.
  • Different thread:

    • Lock: If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes and lies dormant until the lock has been acquired, at which time the lock hold count is set to one.
    • Unlock: If different thread tries to unlock when it is NOT holding the lock then IllegalMonitorStateException is thrown.

That is the reason ReentrantLock lock and unlock mandates you to have try-catch or throw mechanism because it throws exception.

Read below excerpt from ReentrantLock#unlock()

If the current thread is the holder of this lock then the hold count is decremented. If the hold count is now zero then the lock is released. If the current thread is not the holder of this lock then {@link IllegalMonitorStateException} is thrown.

Answer to second question:

I think a lock should be acquired and released in the function itself, before the control is returned from the function. Is my understanding correct?

That's the whole purpose of ReentrantLock, you can extend the locking mechanism to other methods, which you cannot do with synchronized blocks and methods. See below from ReentrantLock

A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities.

like image 91
hagrawal Avatar answered Sep 30 '22 13:09

hagrawal


What if somebody just calls method2 when i am already executing method1/method2 pair? Doesn't it complicate things.

java.util.concurrent.locks.Lock is a more powerful mechanism than synchronized. Power tools are dangerous. Use them with caution.

See @hagrawal's answer for details.

like image 27
Solomon Slow Avatar answered Sep 30 '22 13:09

Solomon Slow