0

我正在阅读 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);
}

我的疑问是:

  1. 为什么放在pthread_mutex_lock(&fp->f_lock)前面pthread_mutex_unlock(&hashlock)?我可以把它放在后面吗?

  2. 由于fp是局部变量,可以pthread_mutex_lock(&fp->f_lock)一起pthread_mutex_unlock(&fp->f_lock)删除吗?

4

2 回答 2

0

我猜有第二个线程循环创建的对象,对它们做一些事情。在这种情况下:

  1. 不,因为循环线程可能会在初始化之前访问新创建的对象。

  2. 不,因为循环线程可能会访问新创建的半初始化对象。

于 2012-12-22T07:19:57.393 回答
0
  1. 不,因为通过pthread_mutex_lock(&hashlock)将新创建的结构添加到fh列表中,之后的操作会将新创建的结构暴露给其他线程。持有哈希锁时,没有人可以访问该变量;一旦散列锁被释放,其他线程就可以通过散列访问它,但是锁定fp_>f_lock互斥锁可以防止任何人弄乱fp.

  2. 不是写的代码。如果除了散列之外整个结构都已初始化,那么您可以不锁定fp->f_lock互斥锁;就在完成之前,您将锁定哈希锁,将新分配的项目挂钩到哈希表中,然后释放哈希锁,这样您就安全了。如果在将结构添加到哈希表后需要任何独占访问,则必须获取其互斥体。它的编写方式是对互斥锁的非等待获取;没有其他进程可以访问该变量。

    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);
    }
    

因此,所做的事情背后有逻辑;它是正确的。

于 2012-12-22T08:26:48.090 回答