如何在pthread中终止睡眠线程?

我有长时间睡觉的线程,然后醒来做些事情,然后再睡觉,像这样:

while(some_condition) { // do something sleep(1000); } 

我怎样才能让这个线程优雅地退出,很快?

我试图使用pthread_cancel() ,但睡眠线程无法取消。 我也尝试改变while循环的条件,但是它仍然需要很长时间才能退出。 而且我不想使用pthread_kill() ,因为它可能会在线程工作时终止。

那么,有什么好主意吗?

Solutions Collecting From Web of "如何在pthread中终止睡眠线程?"

作为sleep的替代方法,您可以使用超时时间为1000毫秒的pthread_cond_timedwait 。 然后当你想退出时,发信号给条件变量。

这与您在C#/ Java中如何使用wait和notify可以做到这一点类似。

经典的UNIX条件变量是自我管道 。

 int fds[2]; pipe2(fds, O_NONBLOCK); // requires newish kernel and glibc; use pipe + 2*fcntl otherwise child: while (some_condition) { // do something struct pollfd pd = { .fd = fds[0], .events = POLLIN }; int rc; char c; while ((rc = poll(&pd, 1, 1000000)) == -1 && errno == EINTR) // not entirely correct; 1000000 should be decreased according to elapsed time when repeating after a signal interruption ; if (rc > 0 && (pd.revents & POLLIN) && read(fds[0], &c, 1) >= 0) break; } parent: cancel() { char c = 0; write(fds[1], &c, 1); } 

是的,这是很多(和未经测试的)代码。 你应该使用pthread_cond_wait ,它需要一个pthread_mutex_t和一个pthread_cond_t但是要容易得多。

你用pthread_cleanup_push和pop吗? 没有它们,使用pthread_cancel取消不起作用。 你必须成对使用它们,就像我在下面的例子中一样。 如果你忘了它不会编译(花式宏,一个有'{',另一个有'}')。 你甚至可以嵌套不同级别的清理/弹出。 无论如何,他们设置了一个跳远点,当取消发生时取消跳转(非常酷)。 此外,如果您的测试程序不等待线程启动或停止,您可能不会注意到取消发生。

例:

 #include <stdio.h> #include <stdlib.h> #include <pthread.h> static void *ThreadProc(void * arg); static void unwind(__attribute__ ((unused)) void *arg); int _fActive = 0; int main(int argc, char** argv) { pthread_t Thread; int nRet; nRet = pthread_create(&Thread, NULL, ThreadProc, NULL); printf("MAIN: waiting for thread to startup...\n"); while (_fActive == 0) nanosleep(&(struct timespec){ 0, 0}, NULL); printf("MAIN: sending cancel...\n"); nRet = pthread_cancel(Thread); printf("MAIN: waiting for thread to exit...\n"); while (_fActive) nanosleep(&(struct timespec){ 0, 0}, NULL); printf("MAIN: done\n"); return 0; } static void unwind(__attribute__ ((unused)) void *arg) { // do some cleanup if u want printf("THREAD: unwind (all threads, canceled or normal exit get here)\n"); _fActive = 0; } static void *ThreadProc(void * arg) { pthread_cleanup_push(unwind, arg); // optional : pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); printf("THREAD: Enter Sleep\n"); _fActive = 1; sleep(1000000); printf("THREAD: Exit Sleep (canceled thread never gets here)\n"); pthread_cleanup_pop(1); printf("THREAD: Exit (canceled thread never gets here)\n"); return NULL; } 

节目输出:

 MAIN: waiting for thread to startup... THREAD: Enter Sleep MAIN: sending cancel... MAIN: waiting for thread to exit... THREAD: unwind (all threads, canceled or normal exit get here) MAIN: done 

注意取消点sleep()中的ThreadProc是如何取消的,只执行unwind()函数。