根据调用线程的变量值关闭线程
Close a thread based on a variable value from calling thread
我在 C 中使用 posix 个线程。我的程序中有两个线程,thread1 和 thread2。线程 1 启动线程 2。
thread1 维护一个变量 var1,基于该变量 thread2 必须安全退出。
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;
}
尽管您的问题无法正确理解,但在下面的代码中,我给出了一个处理问题的想法。使用 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;
}
有几种方法可以做到这一点。这是一个:
从thread1 的角度来看,您可以在时机成熟时在thread2 上简单地使用pthread_cancel
。但是您需要相应地重组 thread2 以确保它在安全的地方有取消点。您还需要重组保存数据的方式,以允许为线程 2 调用取消回调:
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;
}
那么这里发生了什么?
所有需要释放的指针都捆绑在一起并初始化为NULL。如果在分配任何单个变量之前调用清理函数,这允许调用 free
以空操作的方式对它们进行操作。
回调已注册以释放指针。该回调将在任何取消点调用。包括当线程 returns 来自其处理函数时。所以你不需要在那里明确地处理它,除了调用 pop.
取消点在不同的 "safe" 处添加 pthread_testcancel
。因此允许线程在计算之间过早结束。根据需要添加它们。
我在 C 中使用 posix 个线程。我的程序中有两个线程,thread1 和 thread2。线程 1 启动线程 2。
thread1 维护一个变量 var1,基于该变量 thread2 必须安全退出。
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;
}
尽管您的问题无法正确理解,但在下面的代码中,我给出了一个处理问题的想法。使用 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;
}
有几种方法可以做到这一点。这是一个:
从thread1 的角度来看,您可以在时机成熟时在thread2 上简单地使用pthread_cancel
。但是您需要相应地重组 thread2 以确保它在安全的地方有取消点。您还需要重组保存数据的方式,以允许为线程 2 调用取消回调:
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;
}
那么这里发生了什么?
所有需要释放的指针都捆绑在一起并初始化为NULL。如果在分配任何单个变量之前调用清理函数,这允许调用
free
以空操作的方式对它们进行操作。回调已注册以释放指针。该回调将在任何取消点调用。包括当线程 returns 来自其处理函数时。所以你不需要在那里明确地处理它,除了调用 pop.
取消点在不同的 "safe" 处添加
pthread_testcancel
。因此允许线程在计算之间过早结束。根据需要添加它们。