I’m reading APUE and I am confused with thread synchronization of chapter 11. Below is a code snippet.
#define NHASH 29
#define HASH(fp) (((unsigned long)fp)%NHASH)
struct foo *fh[NHASH];
pthread_mutex_t hashlock = PTHREAD_MUTEX_INITIALIZER;
struct foo {
int f_count;
pthread_mutex_t f_lock;
struct foo *f_next; /* protected by hashlock */
int f_id;
/* ... more stuff here ... */
};
struct foo *
foo_alloc(void) /* allocate the object */
{
struct foo *fp;
int idx;
if ((fp = malloc(sizeof(struct foo))) != NULL) {
fp->f_count = 1;
if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
free(fp);
return(NULL);
}
idx = HASH(fp);
pthread_mutex_lock(&hashlock);
fp->f_next = fh[idx];
fh[idx] = fp;
pthread_mutex_lock(&fp->f_lock);
pthread_mutex_unlock(&hashlock);
/* ... continue initialization ... */
pthread_mutex_unlock(&fp->f_lock);
}
return(fp);
}
My doubts are:
-
Why place
pthread_mutex_lock(&fp->f_lock)before thepthread_mutex_unlock(&hashlock)? Could I place it afterward instead? -
Since
fpis local variable, couldpthread_mutex_lock(&fp->f_lock)andpthread_mutex_unlock(&fp->f_lock)be removed all together?
No, because the actions after the
pthread_mutex_lock(&hashlock)expose the newly created structure to other threads by adding it to the thefhlist. While the hashlock is held, no-one can access the variable; as soon as the hashlock is released, it becomes accessible to other threads via the hash, but locking thefp_>f_lockmutex prevents anyone messing withfp.Not with the code as written. If the whole structure was initialized except for the hashing, then you could do without locking the
fp->f_lockmutex; just before completing, you’d lock the hashlock, hook the newly allocated item into the hash tables, and then release the hashlock, and you would be safe. If you need any exclusive access after the structure is added into the hash table, you have to acquire its mutex. The way it is written, that’s a non-waiting acquisition of the mutex; there is no other process that could have access to the variable.So, there is logic behind what is done; it is correct.