进击的code儿 2022-06-08 02:08 采纳率: 100%
浏览 111
已结题

关于Linux下pthread_join()无法回收资源的问题

问题遇到的现象和发生背景

Linux编写多线程代码时遇到的问题:使用的pthread_join()并没有对所有线程资源进行回收,仅回收了部分线程后,一直处于阻塞状态。

问题相关代码
#include<iostream>
#include<pthread.h>
#include<signal.h>
#include<unistd.h>
using namespace std;

#define N 10      // food总生产个数
#define TID_NUM 10 // 线程个数, 如果大于3, 就会产生问题

static int food = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;

int cnt1 = 0;
int cnt2 = 0;

void* thread_cook(void* arg)
{
    int tid = *((int*)arg);
    for (int i = 1; i <= N; ++i)
    {
        pthread_mutex_lock(&mutex);
        ++food;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
        ++cnt1;
    }
    sleep(1);
    pthread_cond_broadcast(&cond); // 通知所有正在等待的人(唤醒所有处于等待队列中的线程)
    return NULL;
}

void* thread_eat(void* arg)
{
    pthread_t tid = *((pthread_t*)arg);
    while (cnt2 < N) //可能有晚来的线程, 那么可能会看到今天的食物发完了 "那没我事了,先走了"。
    {
        pthread_mutex_lock(&mutex);
        if (food <= 0) pthread_cond_wait(&cond, &mutex);
        if (cnt2 == N) // 唤醒却被告知,食物已经发完了啦
        {
            break; // 退场(回收线程资源)
        }
        cout << tid << " eat 1, left " << --food << endl;
        ++cnt2;
        pthread_mutex_unlock(&mutex);
        sleep(0.01); // 使多线程交替执行
    }
    return NULL;
}

int main()
{
    pthread_mutex_init(&mutex, NULL);

    pthread_t tid[TID_NUM]; 
    pthread_create(&tid[0], NULL, thread_cook, (void*)&tid[0]);
    for (int i = 1; i < TID_NUM; ++i)
        pthread_create(&tid[i], NULL, thread_eat, (void*)&tid[i]);

    /*
       不理解:下面的pthread_join()为什么会存在个别线程无限阻塞的情况,
       解决方案:将线程个数减少到3的时候,就没有问题了,但问题所在仍未知
    */
    for (int i = 0; i < TID_NUM; ++i)
    {
        pthread_join(tid[i], NULL); // 真正回收joinable线程资源
        cout << i << endl;
    }

    cout << "created food: " << cnt1 << endl;
    cout << "eat total: " << cnt2 << endl;

    pthread_mutex_destroy(&mutex);
    return 0;
}

运行结果及报错内容

img

程序一直阻塞无法退出,上图中的0和1结果表明,pthread_join仅回收了两个线程的资源。


我的解答思路和尝试过的方法

方法1:因为pthread_cook线程和pthread_eat线程不一样,pthread_cook线程一定要在pthread_eat线程退出之前,保证它食物都能被pthread_eat得到。所以pthread_cook通过pthread_join()单独进行回收,其余的pthread_eat线程由pthread_detach进行回收,就需要将pthread_eat线程从连接的状态(joinable)转变成分离状态(detached),我采用的是pthread_attr_init()方法,将pthread_create()中的attr属性设置为PTHREAD_CREATE_DETACHED,之后在线程执行语句的最后通过pthread_detach(pthread id)就可以对其进行回收了,从而达到下图展示的结果。
方法2:和上面方法一大致一样,只不过是将pthread_detach(self())置于pthread_eat线程开始位置,然后在main函数后面对其所有线程执行pthread_detach(线程id)。

方法3(疑惑所在):
对于pthread_join()函数的问题,产生疑惑,后面发现当线程个数为3的时候,即1个cook线程和2个eat线程,就不会产生上面无限阻塞的问题。这就是我主要疑惑的地方,麻烦帮忙解答一下!**


我想要达到的结果

img

  • 写回答

1条回答 默认 最新

  • make-n 2022-06-08 02:57
    关注

    至少有两个问题,1,cond没有初始化,2,break跳出时mutex没有释放,对其他线程可能会造成死锁卡死。所以join等不到所有线程结束。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 6月8日
  • 已采纳回答 6月8日
  • 创建了问题 6月8日

悬赏问题

  • ¥15 对于这个复杂问题的解释说明
  • ¥50 三种调度算法报错 采用的你的方案
  • ¥15 关于#python#的问题,请各位专家解答!
  • ¥200 询问:python实现大地主题正反算的程序设计,有偿
  • ¥15 smptlib使用465端口发送邮件失败
  • ¥200 总是报错,能帮助用python实现程序实现高斯正反算吗?有偿
  • ¥15 对于squad数据集的基于bert模型的微调
  • ¥15 为什么我运行这个网络会出现以下报错?CRNN神经网络
  • ¥20 steam下载游戏占用内存
  • ¥15 CST保存项目时失败