Monday, October 03, 2016

reentrant lock, unlock

Given two primitive locking constructs, write reentrant acquire() and release().
// blocks others
acquire(obj):
// unblocks others, throws ex if called without lock(obj) first
release(obj):
acquire(obj) should be called as early as possible. release(obj) should be called as late as possible.

acquire(obj) cannot be the 1st statement for lock(obj) to be reentrant. It is ok if 1+ threads pass the if as acquire(obj) will allow only 1st thread and block others.

Calling release(obj) without acquire(obj) will throw.
locker:
    obj
    count = 0
    thread = null
    //ctor
    locker(obj):
        obj = obj

    lock():
        // any other thread gets blocked (reentrant)
        if thread != thread.current:
            acquire(obj)
            thread = thread.current
        count++
    unlock():
        if thread != thread.current:
            throw //as release called without lock
        count--
        if count == 0:
            thread = null
            // unblocks blocked threads
            release(obj)
Used as:
lockobj1 = new locker(obj1)
lockobj1.lock() //1st
// critical section
// ok to call lock() again
lockobj1.lock() //2nd
...
lockobj1.unlock() //2nd
lockobj1.unlock() //1st
[Hat tip to PK]

No comments:

Post a Comment