我测试了线程取消过程,并有这样的代码。 它在我的 ARM 机器上工作,有时工作正常,有时导致段错误,有时创建后卡住。
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
void *t(void *ptr)
{
printf("in t\n");
sleep(0.3);
return NULL;
}
int main() {
pthread_t p;
pthread_create(&p, NULL, t, NULL);
printf("created\n");
pthread_detach(p);
pthread_cancel(p);
printf("canceled\n");
return 0;
}
不知道哪个部分导致了问题(卡住/段错误)。
我18年前回答过同样的问题。在分离的线程上调用
pthread_cancel
是不安全的。
您的代码存在竞争条件,因此其行为未定义。如果线程在您调用
pthread_cancel
之前设法终止,则您正在向 pthread_cancel
传递无效参数,这是未定义的行为。
如果
main
中的代码正在管理线程的生命周期,请不要分离它,否则无法确保线程ID保持有效。如果 main
中的代码不管理线程的生命周期,请勿在其中调用 pthread_cancel
。您永远找不到安全的方法来平分差额。
您应该将
pthread_detach
视为使线程 ID 无效(或用 Glenn Burkhardt 的话说“语义上关闭”),并且不要再次使用它。
正如一些程序员家伙指出的那样,你的
sleep
四舍五入为零,这使得更有可能遇到竞争条件。
确保:
pthread_cancel(p);
之前被调用:
pthread_detach(p);
你会没事的。更多细节,为什么它有效,可以在这个答案中找到:Is it safe to call pthread_cancel() on returned thread?
通常,在调用
pthread_join()
或 pthread_detach()
后,不得再使用线程标识符。