I've never had the chance to play with the pthreads library before, but I am reviewing some code involving pthread mutexes. I checked the documentation for pthread_mutex_lock
and pthread_mutex_init
, and my understanding from reading the man pages for both these functions is that I must call pthread_mutex_init
before I call pthread_mutex_lock
.
However, I asked a couple colleagues, and they think it is okay to call pthread_mutex_lock
before calling pthread_mutex_init
. The code I'm reviewing also calls pthread_mutex_lock
without even calling pthread_mutex_init
.
Basically, is it safe and smart to call pthread_mutex_lock
before ever calling pthread_mutex_init
(if pthread_mutex_init
even gets called)?
EDIT: I also see some examples where pthread_mutex_lock
is called when pthread_mutex_init
is not used, such as this example
EDIT #2: Here is specifically the code I'm reviewing. Please note that the configure function acquires and attaches to some shared memory that does not get initialized. The Java code later on will call lock()
, with no other native functions called in-between. Link to code
Mutexes are variables containing state (information) that functions need to do their job. If no information was needed, the routine wouldn't need a variable. Likewise, the routine can't possibly function properly if you feed random garbage to it.
Most platforms do accept a mutex object filled with zero bytes. This is usually what pthread_mutex_init
and PTHREAD_MUTEX_INITIALIZER
create. As it happens, the C language also guarantees that uninitialized global variables are zeroed out when the program starts. So, it may appear that you don't need to initialize pthread_mutex_t
objects, but this is not the case. Things that live on the stack or the heap, in particular, often won't be zeroed.
Calling pthread_mutex_init
after pthread_lock
is certain to have undesired consequences. It will overwrite the variable. Potential results:
- The mutex gets unlocked.
- A race condition with another thread attempting to get the lock, leading to a crash.
- Resources leaked in the library or kernel (but will be freed on process termination).
The POSIX standard says:
If mutex
does not refer to an initialized mutex object, the behavior
of pthread_mutex_lock()
, pthread_mutex_trylock()
, and
pthread_mutex_unlock()
is undefined.
So you do need to initialise the mutex. This can be done either by a call to pthread_mutex_init()
; or, if the mutex has static storage duration, by using the static initializer PTHREAD_MUTEX_INITIALIZER
. Eg:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
here is the text from the link I posted in a comment:
Mutual exclusion locks (mutexes) prevent multiple threads
from simultaneously executing critical sections of code that
access shared data (that is, mutexes are used to serialize
the execution of threads). All mutexes must be global. A
successful call for a mutex lock by way of mutex_lock()
will cause another thread that is also trying to lock the
same mutex to block until the owner thread unlocks it by way
of mutex_unlock(). Threads within the same process or
within other processes can share mutexes.
Mutexes can synchronize threads within the **same process** or
in ***other processes***. Mutexes can be used to synchronize
threads between processes if the mutexes are allocated in
writable memory and shared among the cooperating processes
(see mmap(2)), and have been initialized for this task.
Initialize Mutexes are either intra-process or inter-process,
depending upon the argument passed implicitly or explicitly to the initialization of that mutex.
A statically allocated mutex does not need to be explicitly initialized;
by default, a statically allocated mutex is initialized with all zeros and its scope is set to be within the calling process.
For inter-process synchronization, a mutex needs to be allo-
cated in memory shared between these processes. Since the
memory for such a mutex must be allocated dynamically, the
mutex needs to be explicitly initialized using mutex_init().
also, for inter-process synchronization,
besides the requirement to be allocated in shared memory,
the mutexes must also use the attribute PTHREAD_PROCESS_SHARED,
otherwise accessing the mutex from another process than its creator results in undefined behaviour
(see this: linux.die.net/man/3/pthread_mutexattr_setpshared):
The process-shared attribute is set to PTHREAD_PROCESS_SHARED to permit a
mutex to be operated upon by any thread that has access to the memory
where the mutex is allocated, even if the mutex is allocated in memory that is shared by multiple processes