1

我在 C 中使用 posix 线程。我的程序中有两个线程,thread1 和 thread2。线程 1 启动线程 2。

thread1 维护一个变量 var1,基于该变量必须安全退出 thread2。

thread2 调用许多冗长的函数(其运行时间最长可达 5 秒)。在thread2中有很多使用malloc的内存分配。一旦 var1 变为真,我需要关闭 thread2,但只有在释放所有分配的内存之后。如何做到这一点?

代码如下所示:

void * func1(void *arg)
{
   pthread_create(&thread2, &attr, func2, NULL);
   while(1)
   {
      // ...
      var1 = func3();
      if(var1 == true)
      {   
          // Cancel thread2
      }
      // ...
   }
}

void * func2(void *arg)
{
    // ...
    func4(); // runs for 2 sec
    char* var2 = malloc(10);
    func5(); // runs for 5 sec
    char* var3 = malloc(20);
    // ...
 cleanup:
    free(var2);
    free(var3);
    return (void*) 0;
}
4

2 回答 2

4

有几种方法可以做到这一点。这是一个:

从 thread1 的角度来看,您可以pthread_cancel在时机成熟时简单地在 thread2 上使用。但是您需要相应地重组 thread2 以确保它在安全的地方有取消点。您还需要重新构建保存数据的方式,以允许为 thread2 调用取消回调:

struct func2_data {
  char *var2;
  char *var3;
};

void func2_cleanup(void *vdata) {
  struct func2_data *data = vdata;
  free(data->var2);
  free(data->var3);
}

void * func2(void *arg)
{
  struct func2_data data = {
    NULL, NULL
  };

  pthread_cleanup_push(func2_cleanup, &data);

  // ....    

  func4();
  data.var2 = malloc(10);
  pthread_testcancel();

  func5();
  data.var3 = malloc(10);
  pthread_testcancel();

  // ....        

  pthread_cleanup_pop(1);
  return NULL;
}

那么这里会发生什么?

  1. 所有需要释放的指针都捆绑在一起并初始化为 NULL。如果在分配任何单个变量之前调用清理函数,则这允许调用将free它们作为无操作执行。

  2. 注册回调以释放指针。该回调将在任何取消点被调用。包括线程从其处理函数返回的时间。所以你不需要在那里明确地处理它,除了调用 pop.

  3. pthread_testcancel在各种“安全”的地方添加取消点。因此允许线程在计算之间过早结束。根据需要添加它们。

于 2017-03-06T09:56:16.850 回答
1

尽管您的问题无法正确理解,但在下面的代码中,我给出了一个处理这些事情的想法。用于ptread_join线程的安全退出

void * func1(void *arg)
{
    pthread_create(&thread2, &attr, func2, (void*)&var1); /* Pass addr of var1 as argument to thread*/
    while(1)
    {
        ...
        var1 = func3();
        if(var1 == TRUE){
            int *ret;
            pthread_join(thread2,&ret);
        }
        ...
    }
}

void * func2(void *arg)
{
    bool *check = (bool*)arg;
    ...
    func4(); // runs for 2 sec
    if(*check == TRUE)
        goto end;
    char* var2 = malloc(10);
    func5(); // runs for 5 sec
    if(*check == TRUE)
        goto clean_var2;
    char* var3 = malloc(20);
    ...
    cleanup:
    free(var3);
    clean_var2:
    free(var2);
    end:
    return (void*) 0;
}
于 2017-03-06T09:40:10.007 回答