简体   繁体   English

APUE的线程同步问题

[英]Thread synchronization issues of APUE

I'm reading APUE and I am confused with thread synchronization of chapter 11. Below is a code snippet. 我正在阅读APUE,并且对第11章的线程同步感到困惑。下面是一个代码片段。

#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: 我的怀疑是:

  1. Why place pthread_mutex_lock(&fp->f_lock) before the pthread_mutex_unlock(&hashlock) ? 为什么地方pthread_mutex_lock(&fp->f_lock)之前pthread_mutex_unlock(&hashlock) Could I place it afterward instead? 我可以把它放在后面吗?

  2. Since fp is local variable, could pthread_mutex_lock(&fp->f_lock) and pthread_mutex_unlock(&fp->f_lock) be removed all together? 由于fp是局部变量,是否可以一起删除pthread_mutex_lock(&fp->f_lock)pthread_mutex_unlock(&fp->f_lock)

I guess that there's a second thread that's looping through the created objects, doing something with them. 我猜还有第二个线程循环遍历创建的对象,并对它们进行处理。 In this case: 在这种情况下:

  1. No, because the loop thread might access the newly created object before being initialized at all. 否,因为循环线程可能会在初始化之前访问新创建的对象。

  2. No, because the loop thread might access the newly created object being half initialized. 否,因为循环线程可能会访问刚刚初始化一半的新创建的对象。

  1. No, because the actions after the pthread_mutex_lock(&hashlock) expose the newly created structure to other threads by adding it to the the fh list. 否,因为pthread_mutex_lock(&hashlock)之后的操作通过将新创建的结构添加到fh列表中,将其暴露给其他线程。 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 the fp_>f_lock mutex prevents anyone messing with fp . 散列锁释放后,其他线程就可以通过散列对其进行访问,但是锁定fp_>f_lock互斥锁可以防止任何人混淆fp

  2. 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_lock mutex; 如果除了散列之外,整个结构fp->f_lock初始化,则可以不锁定fp->f_lock互斥锁; 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. 没有其他进程可以访问该变量。

     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); /* ... complete initialization except for adding to hash table ... */ pthread_mutex_lock(&hashlock); fp->f_next = fh[idx]; fh[idx] = fp; pthread_mutex_unlock(&hashlock); } 

So, there is logic behind what is done; 因此,要做的事情背后有逻辑。 it is correct. 它是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM