我正在阅读Richard Stevens在unix环境中的高级编程
线程同步类别中有一个代码(第11章)。
这是显示如何避免相同类型的许多共享结构的竞争条件的代码
此代码显示两个用于同步的互斥锁 - 一个用于列表fh
(一个跟踪所有foo结构的列表)&结构f_next
的{{1}}字段和另一个字段
代码是:
foo
怀疑是
1) #include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#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);
///////////////////// HERE -----------------
fp->f_next = fh[idx];
fh[idx] = fp->f_next;
//////////////////// UPTO HERE -------------
pthread_mutex_lock(&fp->f_lock);
pthread_mutex_unlock(&hashlock);
/* ... continue initialization ... */
pthread_mutex_unlock(&fp->f_lock);
}
return(fp);
}
void foo_hold(struct foo *fp) /* add a reference to the object */
.......
预处理器在做什么?
我知道它是对HASH(fp)
存储然后取其模数进行类型转换。但是,在函数fp
中,我们只是传递新分配的foo结构的地址
为什么我们这样做我知道这会给我一个0到28之间的整数 - 存储在数组foo_alloc
中。但为什么我们采用模数地址。为什么有这么多随机化?
2)假设我接受了这一点,现在这两条线正在做什么(在代码中也突出显示):
fh
我希望最初fp->f_next = fh[idx];
fh[idx] = fp->f_next;
有任何垃圾值,我分配给foo的fh[idx]
字段,并在下一行中发生了什么,同样的任务,但顺序相反。
答案 0 :(得分:0)
struct foo *fh[NHASH]
是一个哈希表,并使用HASH
宏作为哈希函数。
1)HASH(fp)
计算索引,以决定fh
存储fp
的位置,并使用fp
的地址并将地址用作关键字计算指数。我们可以轻松地将地址类型转换为long类型。
2)使用链表来避免称为单独链接的哈希冲突,我认为以下鳕鱼是正确的,您可以在书中查看:
fp->f_next = fh[idx];
fh[idx] = fp;
将fp元素插入到链接列表fh[idx]
的标头中,fh[idx]
的初始值为空。