#include <stdio.h>
#include <pthread.h>
#include <windows.h> // Sleep
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
struct Node
{
int number;
struct Node *next;
} *head = NULL;
// 清理函数
void cleanup_handler(void *node)
{
printf("Cleanup handler of second thread.\n");
free(node);
pthread_mutex_unlock(&mtx);
}
void* thread_func(void *arg)
{
struct Node *p = NULL;
// 清理函数入栈,此demo只需一个清理函数
pthread_cleanup_push(cleanup_handler, p);
while (true)
{
pthread_mutex_lock(&mtx);
if (head == NULL)
{
pthread_cond_wait(&cond, &mtx);
}
p = head;
head = head->next;
printf("Got %d from front of queue\n", p->number);
free(p);
pthread_mutex_unlock(&mtx);
}
/* 若从此处终止线程,则属于正常退出,无需清理。所以,只需将清理函数出栈。故而用
参数零。若是从上面的“取消点”退出,则清理函数出栈时被调用:锁被打开,同时释放资源。*/
pthread_cleanup_pop(0);
return 0;
}
int main(int argc, char* argv[])
{
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
for (int i = 0; i < 10; i++)
{
struct Node* p = (Node *)malloc(sizeof(struct Node));
p->number = i;
// <!-- 对head操作属于临界区
pthread_mutex_lock(&mtx);
p->next = head;
head = p;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx);
// 所以要用互斥锁保护起来--!>
Sleep(1);
}
printf("Main thread wants to cancel the 2nd thread.\n");
/* 关于pthread_cancel,有一点额外的说明,它是从外部终止子线程,子线程会在
最近的取消点,退出线程。而在我们的代码里,最近的取消点是pthread_cond_wait()了。*/
pthread_cancel(tid);
pthread_join(tid, NULL);
printf("All done -- exiting\n");
return 0;
}
清理函数的调用时机:
- 调用pthread_exit()时,会调用清理函数;通过return返回的线程不会调用。
- 被别的线程取消的时候,会调用。
- pthread_cleanup_pop()参数为非零时,会调用。