pthread互斥锁实现线程无丢键及编译报错问题求助
问题说明
- 预期目标:通过pthread互斥锁协调多线程对哈希表的读写操作,实现零键丢失
- 现存问题:
- 单线程运行时无键丢失,2线程运行时出现大量键丢失
- 代码添加互斥锁逻辑后,在Ubuntu Linux环境编译出现链接错误
编译链接错误解决方案
你遇到的undefined reference to 'pthread_create'、undefined reference to 'pthread_join'属于链接阶段错误,原因是pthread是独立的线程库,GCC默认不会自动链接该库。
解决方法:编译时在命令中添加-pthread参数,示例编译命令:
gcc thr.c -o thr -pthread
不推荐使用-lpthread参数,-pthread会自动处理线程相关的预编译宏和依赖配置,兼容性更好
多线程键丢失问题修复
你当前添加的互斥锁逻辑完全无效,根本没有起到保护共享资源的作用,核心问题有3个:
- 你在
get()、put_thread()、get_thread()内部定义的都是局部锁变量,每个线程调用函数时会生成独立的锁实例,无法实现跨线程互斥 - 加锁位置完全错误:你是在完成哈希表读写操作之后才执行加锁、解锁,临界区(对共享哈希表的读写逻辑)完全没有被锁保护
- 代码中全局定义的
pthread_mutex_t lock从未被初始化,也没有被实际使用
按以下步骤修复即可:
- 删除
get()、put_thread()、get_thread()三个函数内部所有局部锁定义、初始化、加锁、解锁的冗余代码 - 在
main函数创建线程之前,添加全局锁初始化代码:pthread_mutex_init(&lock, NULL); - 将所有对共享哈希表的读写操作包裹在加锁、解锁逻辑之间,保证临界区操作的原子性:
- 修改
put()函数:进入函数后第一时间加锁,完成键查找、值更新/新节点插入操作后再解锁 - 修改
get()函数:进入函数后第一时间加锁,完成链表遍历查找后再解锁,避免遍历过程中其他线程修改链表结构
- 修改
修复后的核心读写逻辑参考:
static void put(int key, int value) { pthread_mutex_lock(&lock); int i = key % NBUCKET; struct entry *e = 0; for (e = table[i]; e != 0; e = e->next) { if (e->key == key) break; } if(e){ e->value = value; } else { insert(key, value, &table[i], table[i]); } pthread_mutex_unlock(&lock); } static struct entry* get(int key) { pthread_mutex_lock(&lock); int i = key % NBUCKET; struct entry *e = 0; for (e = table[i]; e != 0; e = e->next) { if (e->key == key) break; } pthread_mutex_unlock(&lock); return e; }
额外优化提示:当前使用全局单锁会限制并发性能,后续可以给每个哈希桶分配独立的互斥锁,只在操作对应桶的时候加锁,能大幅降低锁冲突
内容的提问来源于stack exchange,提问作者KhonsusKnight
相关产品推荐
相关产品推荐

