Is it safe to call pthread_mutex_lock before pthre

2019-04-28 13:15发布

问题:

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

回答1:

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:

  1. The mutex gets unlocked.
  2. A race condition with another thread attempting to get the lock, leading to a crash.
  3. Resources leaked in the library or kernel (but will be freed on process termination).


回答2:

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;


回答3:

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


标签: c pthreads mutex