As demonstrated in this answer I recently posted, I seem to be confused about the utility (or lack thereof) of volatile
in multi-threaded programming contexts.<
volatile
is useful (albeit insufficient) for implementing the basic construct of a spinlock mutex, but once you have that (or something superior), you don't need another volatile
.
The typical way of multithreaded programming is not to protect every shared variable at the machine level, but rather to introduce guard variables which guide program flow. Instead of volatile bool my_shared_flag;
you should have
pthread_mutex_t flag_guard_mutex; // contains something volatile
bool my_shared_flag;
Not only does this encapsulate the "hard part," it's fundamentally necessary: C does not include atomic operations necessary to implement a mutex; it only has volatile
to make extra guarantees about ordinary operations.
Now you have something like this:
pthread_mutex_lock( &flag_guard_mutex );
my_local_state = my_shared_flag; // critical section
pthread_mutex_unlock( &flag_guard_mutex );
pthread_mutex_lock( &flag_guard_mutex ); // may alter my_shared_flag
my_shared_flag = ! my_shared_flag; // critical section
pthread_mutex_unlock( &flag_guard_mutex );
my_shared_flag
does not need to be volatile, despite being uncacheable, because
&
operator).
pthread_mutex_lock
is a library function.pthread_mutex_lock
somehow acquires that reference.pthread_mutex_lock
modifes the shared flag!volatile
, while meaningful in this context, is extraneous.