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

线程1维护变量var1,基于该变量必须安全退出线程2。

thread2调用了许多冗长的函数(其运行时间最多为5秒)。在thread2中有许多使用malloc的内存分配。一旦var1变为true,我需要关闭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;
}

最佳答案

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

从线程1的角度来看,您可以在时间到时在线程2上简单地使用pthread_cancel。但是您需要相应地重组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;
}

那么这里发生了什么呢?
  • 所有需要释放的指针都 bundle 在一起,并初始化为NULL。如果在分配任何单个变量之前调用了清除函数,则允许调用free使其作为无操作对象来执行。
  • 注册了回调以释放指针。该回调将在任何取消点被调用。包括线程从其处理函数返回的时间。因此,除了调用pop之外,您无需在那里专门处理它。
  • 在各个“安全”位置,取消点都添加了pthread_testcancel。因此,允许线程在计算之间过早结束。根据需要添加它们。
  • 09-16 00:13
    查看更多