您的位置:首页 > 运维架构 > Linux

pthread_cancel函数注意事项

2017-08-04 20:49 183 查看
/**************************************************
相关函数:
#include <pthread.h>
int pthread_cancel(pthread_t thread)
成功返回0,失败返回错误码
**************************************************/

此函数是POSIX提供的用于取消同一进程中的其它线程,此函
数只发送取消请求,并不等待要取消的进程退出!线程可以
选择忽略或是选择其它动作!

需要注意的是:
当我们调用它取消一个已经获得互斥锁/匿名信号量/写锁....但
还未释放其所获得锁的线程时,如果此线程被取消,此后所有想
要获得此时执行任务的线程都将处于睡眠状态,直到此锁被释放.
为避免此问题的产生,我们可以调用一组函数:
/**************************************************
#include <pthread.h>

void pthread_cleanup_push(void (*routine)(void *), void *arg)
void pthread_cleanup_pop(int execute)
参数解释:routine为函数指针,arg为传递给routine的参数
execute为零时,从栈中删除注册的函数,删除后将再也
不被执行。
**************************************************/
这两个函数被称为线程清理处理程序,类似于atexit函数,我们
可以注册多个清理函数,当执行以下动作时我们所注册的函数将会
回调(执行顺序与注册顺序相反):
1.线程从pthread_exit(void *)函数退出时。
2.线程响应取消请求时。
3.执行pthread_cleanup_pop函数,execute参数为非零时。

这两个线程清理处理程序必须成对出现,必须处于同一作用域中,
否则会编译出错。


实例:
如何使用这些函数处理以上问题!
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <signal.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include <pthread.h>

pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;

void *count(void *arg)
{
int i=1;
while(1)
{
sleep(1);
printf("sec: %d\n", i++);
}
}

void handler(void *arg)
{
printf("[%u] is cancelled.\n", (unsigned)pthread_self());
pthread_mutex_t *pm = (pthread_mutex_t *)arg;

pthread_mutex_unlock(pm);
}

void *routine(void *arg)
{
#ifdef CLEANUP
pthread_cleanup_push(handler, (void *)&m);
#endif

pthread_mutex_lock(&m);
printf("[%u] lock the mutex!\n", (unsigned)pthread_self());

/*
** During sleep(), if the calling thread received a cancel-
** request and HASN'T established any cleanup handlers to
** unlock the mutex, it will leave the mutex a DEAD-LOCK
** state.
*/
sleep(2);
printf("[%u]: job finished!\n", (unsigned)pthread_self());

pthread_mutex_unlock(&m);
printf("[%u] unlock the mutex!\n", (unsigned)pthread_self());

/*
** NOTE:
**
** pthread_cleanup_push() and pthread_cleanup_pop() may be
** implemented as macro that expand to text containing '{'
** and '}', respectively. For this reason, the caller must
** user them pairly and ensure that they are paired within
** a same function and at the same lexical nesting level.
*/
#ifdef CLEANUP
pthread_cleanup_pop(0);
#endif

pthread_exit(NULL);
}

int main(int argc, char **argv)
{
pthread_t t, t1, t2;
pthread_create(&t, NULL, count, NULL);

pthread_create(&t1, NULL, routine, NULL);
pthread_create(&t2, NULL, routine, NULL);
printf("[%u] ==> t1\n", (unsigned)t1);
printf("[%u] ==> t2\n", (unsigned)t2);
printf("[%u] ==> main\n", (unsigned)pthread_self());

sleep(1);
pthread_cancel(t1);
pthread_cancel(t2);

sleep(2);

pthread_mutex_lock(&m);
printf("[%u] locked the mutex!\n",
(unsigned)pthread_self());
pthread_mutex_unlock(&m);

exit(0);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux线程