What is the Re-entrant lock and concept in general?

reentrantlock
reentrantlock java 8
're entrant mutex
reentrant lock c
lock vs synchronized java
locks in java
concurrency lock
synchronization vs reentrantlock

I always get confused. Would someone explain what Reentrant means in different contexts? And why would you want to use reentrant vs. non-reentrant?

Say pthread (posix) locking primitives, are they re-entrant or not? What pitfalls should be avoided when using them?

Is mutex re-entrant?

What are Reentrant Locks?, In Java 5.0, a new addition called Reentrant Lock was made to enhance We can also maintain time budget activities using this concept. I always get confused. Would someone explain what Reentrant means in different contexts? And why would you want to use reentrant vs. non-reentrant? Say pthread (posix) locking primitives, are they

A re-entrant lock lets you write a method M that puts a lock on resource A and then call M recursively or from code that already holds a lock on A.

With a non re-entrant lock, you would need 2 versions of M, one that locks and one that doesn't, and additional logic to call the right one.

Reentrant Lock in Java, Reentrant Locks are provided in Java to provide synchronization with Get hold of all the important DSA concepts with the DSA Self Paced� Interruptible lock acquisition allows locking to be used within cancellable activities. The lockInterruptiblymethod allows us to try and acquire a lock while being available for interruption. So,

Reentrant lock is very well described in this tutorial.

The example in the tutorial is far less contrived than in the answer about traversing a graph. A reentrant lock is useful in very simple cases.

Reentrancy (computing), In computing, a computer program or subroutine is called reentrant if multiple invocations can safely run concurrently. The concept applies even on a single processor system, where a reentrant is reentrant; however, it is not thread-safe, since there are no locks employed, "General Programming Concepts" (PDF). The ReentrantLock class implements the Lock interface and provides synchronization to methods while accessing shared resources. The code which manipulates the shared resource is surrounded by calls to lock and unlock method.

The what and why of recursive mutex should not be such a complicated thing described in the accepted answer.

I would like to write down my understanding after some digging around the net.


First, you should realize that when talking about mutex, multi thread concepts is definitely involved too. (mutex is used for synchronization. I don't need mutex if I only have 1 thread in my program)


Secondly, you should know the difference bewteen a normal mutex and a recursive mutex.

Quoted from APUE:

(A recursive mutex is a) A mutex type that allows the same thread to lock it multiple times without first unlocking it.

The key difference is that within the same thread, relock a recursive lock does not lead to deadlock, neither block the thread.

Does this mean that recusive lock never causes deadlock? No, it can still cause deadlock as normal mutex if you have locked it in one thread without unlocking it, and try to lock it in other threads.

Let's see some code as proof.

  1. normal mutex with deadlock
#include <pthread.h>
#include <stdio.h>

pthread_mutex_t lock;


void * func1(void *arg){
    printf("thread1\n");
    pthread_mutex_lock(&lock);
    printf("thread1 hey hey\n");

}


void * func2(void *arg){
    printf("thread2\n");
    pthread_mutex_lock(&lock);
    printf("thread2 hey hey\n");
}

int main(){
    pthread_mutexattr_t lock_attr;
    int error;
//    error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
    error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_DEFAULT);
    if(error){
        perror(NULL);
    }

    pthread_mutex_init(&lock, &lock_attr);

    pthread_t t1, t2;

    pthread_create(&t1, NULL, func1, NULL);
    pthread_create(&t2, NULL, func2, NULL);

    pthread_join(t2, NULL);

}

output:

thread1
thread1 hey hey
thread2

common deadlock example, no problem.

  1. recursive mutex with deadlock

Just uncomment this line error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE); and comment out the other one.

output:

thread1
thread1 hey hey
thread2

Yes, recursive mutex can also cause deadlock.

  1. normal mutex, relock in the same thread
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

pthread_mutex_t lock;


void func3(){
    printf("func3\n");
    pthread_mutex_lock(&lock);
    printf("func3 hey hey\n");
}

void * func1(void *arg){
    printf("thread1\n");
    pthread_mutex_lock(&lock);
    func3();
    printf("thread1 hey hey\n");

}


void * func2(void *arg){
    printf("thread2\n");
    pthread_mutex_lock(&lock);
    printf("thread2 hey hey\n");
}

int main(){
    pthread_mutexattr_t lock_attr;
    int error;
//    error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
    error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_DEFAULT);
    if(error){
        perror(NULL);
    }

    pthread_mutex_init(&lock, &lock_attr);

    pthread_t t1, t2;

    pthread_create(&t1, NULL, func1, NULL);
    sleep(2); 
    pthread_create(&t2, NULL, func2, NULL);

    pthread_join(t2, NULL);

}

output:

thread1
func3
thread2

Deadlock in thread t1, in func3. (I use sleep(2) to make it easier to see that the deadlock is firstly caused by relocking in func3)

  1. recursive mutex, relock in the same thread

Again, uncomment the recursive mutex line and comment out the other line.

output:

thread1
func3
func3 hey hey
thread1 hey hey
thread2

Deadlock in thread t2, in func2. See? func3 finishes and exits, relocking does not block the thread or lead to deadlock.


So, last question, why do we need it ?

For recursive function (called in multi-threaded programs and you want to protect some resource/data).

E.g. You have a multi thread program, and call a recursive function in thread A. You have some data that you want to protect in that recursive function, so you use the mutex mechanism. The execution of that function is sequential in thread A, so you would definitely relock the mutex in recursion. Use normal mutex causes deadlocks. And resursive mutex is invented to solve this.

See an example from the accepted answer When to use recursive mutex?.

The Wikipedia explains the recursive mutex very well. Definitely worth for a read. Wikipedia: Reentrant_mutex

Recursive (Re-entrant) Locks, Time for another potentially-controversial subject: recursive locks, also known as Recursive Locks: Definition There are several reasons why I think recursive locks are a poor choice in general, and only one situation� Can someone please explain the concept behind re-entrant and non re-entrant locks? Thank you

Writing reentrant and threadsafe code, This section provides information about writing reentrant and threadsafe programs. It does not cover A threadsafe function protects shared resources from concurrent access by locks. Thread Parent topic: General programming concepts� A reentrant interrupt handler is an interrupt handler that re-enables interrupts early in the interrupt handler. This may reduce interrupt latency. In general, while programming interrupt service routines, it is recommended to re-enable interrupts as soon as possible in the interrupt handler. This practice helps to avoid losing interrupts.

ReentrantLock (Java Platform SE 7 ), A ReentrantLock is owned by the thread last successfully locking, but not yet unlocking it. A thread invoking lock will return, successfully acquiring the lock, when� What is the Re-entrant lock and concept in general? (2) I always get confused. Would someone explain what Reentrant means in different contexts? And why would you want to use reentrant vs. non-reentrant? Say pthread (posix) locking primitives, are they re-entrant or not? What pitfalls should be avoided when using them?

Locks in Java, Lock Reentrance. Synchronized blocks in Java are reentrant. This means, that if a Java thread enters a synchronized block of code, and thereby� What is the Re-entrant lock and concept in general? 3 answers So , a reentrant lock increments the count by one if the current thread acquires the lock again. what i am unable to understand is why and how that helps or benefits us?

Comments
  • Although such situations should usually be avoided anyway, as it makes it hard to avoid deadlock etc as well. Threading is hard enough anyway without being in doubt as to whether you've already got a lock.
  • +1, also consider the case where the lock is NOT reentrant, you can block on yourself if you're not careful. Plus in C, you don't have the same mechanisms other languages do to ensure the lock is Released as many times as it is Acquired. This can lead to big problems.
  • that's exact ly what happened to me yesterday: I didn't take the issue of re-entrancy into a consideration and ended up debugging a deadlock for 5 hours...
  • @Jon Skeet - I think there are probably situations (see my somewhat contrived example above) where keeping track of locks is impractical due to performance or other considerations.
  • Does this mean if i have recursive calls acquiring same lock obj more than once - say x times by a given thread, i can't interleave the execution without releasing all the recursively acquired locks (same lock but for x number of times)? If true, then it essentially makes this implementation sequential. Am i missing something?
  • That shouldn't be a real worlld problem. It's more about granular locking and that a Thread won't lock itself out.