Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to alter the recursive locking behaviour of Windows Mutex?

Windows Mutex seems to allow an acquired lock to be acquired again (recursively) if the thread currently owning the lock tries to acquire it.

But, posix based pthread locks don't allow such a behaviour.

Is there any compile time macro or any settings which can make the windows mutex behave in the same way as the pthread mutex?

like image 655
Jay Avatar asked Jan 01 '10 10:01

Jay


People also ask

What is a recursive mutex lock?

In computer science, the reentrant mutex (recursive mutex, recursive lock) is a particular type of mutual exclusion (mutex) device that may be locked multiple times by the same process/thread, without causing a deadlock.

Why are recursive mutexes bad?

Using recursive mutexes encourages you to not think your concurrency design clearly. There is no long term benefit in using recursive mutexes. Recursive mutexes are technical debt.

How do you lock a mutex?

First, we need to declare a lock variable of type Mutex. Second, before entering the critical section that is protected by that lock, execute the Lock() method of that lock. Third, before exiting the critical section, execute the Unlock() method of the lock.

How do recursive locks work?

Recursive Locks: Definition Recursive locks usually use a reference counting mechanism so that they can be acquired several times and then released several times, but the lock is only actually unlocked when it has been released as many times as it has been acquired.


2 Answers

You cannot alter the fact that Windows Mutexes are recursive. And while Posix threads are not recursive by default, you can use pthread_mutexattr_settype() with the PTHREAD_MUTEX_RECURSIVE flag to make one so.

Locking a mutex in Windows is actually quite an expensive operation, and best suited to inter-process synchronisation. For a mutex used only within a single process, a critical section is normally used, however these are re-entrant also. As nobugz states, you would need to use a semaphore, initialised with a maximum count of 1, to get non-recursive synchronisation.

A semaphore object is like a special counter, that can be atomically incremented and decremented across threads (or processes, if created shared). By creating one with a maximum count of 1, you get the non-recursive behaviour you require.

  • MSDN: Critical Section objects
  • MSDN: Semaphore objects
like image 193
gavinb Avatar answered Sep 21 '22 00:09

gavinb


As long as you program in Windows, avoid reimplementing the behavior of its Mutex. It being re-entrant by the same thread is absolutely essential for its defined behavior.

A sync object without thread affinity is a semaphore that counts to 1. Use CreateSemaphore().

Fwiw, it is very curious that you need this kind of behavior. It sounds like you are trying to use the same sync object in multiple places inappropriately. You can use the semaphore but you'll lose concurrency potential. Consider using more than one mutex instead.

like image 34
Hans Passant Avatar answered Sep 21 '22 00:09

Hans Passant