2012-12-22 105 views
0

我正在阅读APUE,我对第11章的线程同步感到困惑。下面是一段代码片段。APUE线程同步问题

#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_unlock(&hashlock)前放置pthread_mutex_lock(&fp->f_lock)?我可以把它放在后面吗?

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

回答

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

所以,后面有什么做的逻辑;它是正确的。

0

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

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

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