You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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从未被初始化,也没有被实际使用

按以下步骤修复即可:

  1. 删除get()、put_thread()、get_thread()三个函数内部所有局部锁定义、初始化、加锁、解锁的冗余代码
  2. 在main函数创建线程之前,添加全局锁初始化代码:pthread_mutex_init(&lock, NULL);
  3. 将所有对共享哈希表的读写操作包裹在加锁、解锁逻辑之间,保证临界区操作的原子性:
    • 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 00:48:16