Yeah, could be a "false positive".
On the other hand, think about this: The function
pthread_mutex_unlock()
is
not just a single "atomic" CPU instruction; it is a complex function implemented in libpthread. All we really know is that, at some point in
pthread_mutex_unlock()
, the mutex will be marked as "not currently locked", so that the other thread can proceed. But, does
pthread_mutex_unlock()
return
immediately after that point? Is it guaranteed that
pthread_mutex_unlock()
won't access the
pthread_mutex_t
struct after that point, before returning? I don't think so, because this is an implementation detail that we
should not make any assumptions about. Better assume the "worst" case 😏
In other words, your
example()
function does
not wait until
pthread_mutex_unlock()
actually has fully
returned inside of the
runThread()
function; it only waits until the
runThread()
function has (at least)
begun its
pthread_mutex_unlock()
operation.
Surely, any kind of "concurrent" or "interleaved"
pthread_mutex_lock()
or
pthread_mutex_unlock()
invocations on the
same pthread_mutex_t
must always be safe, assuming that the
pthread_mutex_t
was properly initialized. Meanwhile,
destorying the
pthread_mutex_t
while an
pthread_mutex_unlock()
still
might be in progress probably results in
undefined behavior!
I think it's a good guideline to only destroy "shared" resources after all (other) threads that might access those resources have terminated.
________
EDIT: Is it really necessary to create a new
pthread_mutex_t
and
pthread_cond_t
for each thread? You could simply create those
once and re-use them. This eliminates the need to destroy them (except when your program terminates). Note that your variables are declared
static
, so you can only have
one mutex
and
cond
at a time anyways. Doesn't make much sense to destroy + re-create them continuously...
EDIT²: If you want to be sure that multiple threads have passed a certain point, consider using a
pthread_barrier
:
https://www.daemon-systems.org/man/pthread_barrier.3.html
(But, of course, this creates the new problem of when to call the
pthread_barrier_destroy
function 😏)