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

结构体中使用pthread_mutex_t指针替代全局互斥锁引发多线程异常问题排查

你的多线程互斥锁问题根源:内存分配错误导致的未定义行为

兄弟,我一眼就揪出你代码里的致命问题了——线程ID数组的内存分配完全错了!这就是为什么用全局锁能正常跑,换成结构体指针就各种炸的原因,跟互斥锁本身半毛钱关系都没有,纯粹是内存越界把其他数据搞崩了。

问题出在哪?

你在main函数里写了这么一行:

id = malloc(sizeof(int) * n); // allocate id[n]

但id是pthread_t*类型,你却按int的大小来分配内存。在绝大多数现代系统里,pthread_t的尺寸都比int大(比如64位系统里int是4字节,pthread_t是8字节),这就导致你分配的内存空间根本装不下n个pthread_t对象。

接下来的操作直接触发了内存越界写入:

  • 当你循环调用pthread_create(&id[i], ...)时,会往这块不够大的内存里写入线程ID,写着写着就会溢出,覆盖后面的内存区域——刚好你后面分配的mutex和duck链表的内存就在附近,直接把互斥锁的内部状态或者链表指针给搞坏了。
  • 这就解释了你遇到的所有诡异现象:
    • 段错误:访问被破坏的链表指针或互斥锁结构
    • 无限等待:线程ID被破坏,pthread_join找不到正确的线程
    • 断言失败:互斥锁的内部字段(比如__owner)被越界写改成了非法值

而用全局互斥锁的时候,全局变量的内存不在堆上的这块越界区域里,没被破坏,所以程序能侥幸跑起来——但线程ID数组的问题依然存在,只是没影响到全局锁而已。

怎么修复?

只需要把内存分配那行改成按pthread_t的大小分配就行:

id = malloc(sizeof(pthread_t) * n); // 正确分配pthread_t类型的数组

另外,建议你加上内存分配失败的检查,避免后续操作访问空指针:

n = 5; // number of threads
id = malloc(sizeof(pthread_t) * n);
mutex = malloc(sizeof(pthread_mutex_t));
if (!id || !mutex) {
    perror("malloc failed");
    exit(EXIT_FAILURE);
}
pthread_mutex_init(mutex, NULL);
duck = init_chain_ducks(mutex, n);
if (!duck) {
    perror("init_chain_ducks failed");
    // 记得先释放已分配的内存再退出
    free(id);
    free(mutex);
    exit(EXIT_FAILURE);
}

最后,程序结束后别忘了清理内存,避免泄漏:

// 释放duck链表
struct s_duck *temp;
while (duck) {
    temp = duck;
    duck = duck->next;
    free(temp);
}
// 销毁互斥锁并释放内存
pthread_mutex_destroy(mutex);
free(mutex);
free(id);

总结

这是典型的类型不匹配导致的内存越界问题,错误表现出来的症状和实际根源看起来不相关,很容易迷惑人。以后分配数组的时候,一定要用目标类型的sizeof,别想当然用int代替!

内容的提问来源于stack exchange,提问作者hugogogo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 09:54:04