/**
* @file demo1.c
* @Synopsis 线程终止
*
* 1: 线程使用return (这种方法对线程还适用,从main函数return 相当于调用exit)
* 2: 调用pthread_cancel (一个线程可以调用pthread_cancel终止同一进程中的另一个线程)
* 3: 调用pthread_exit(线程可以调用pthread_exit终止自己,有两种情况需要注意:
* 一种情况是,在主线程中,如果从main函数返回或是调用了exit函数退出主线程,
* 则整个进程将终止,此时进程中有线程也将终止,因此在主线程中不能过早地从main
* 函数返回;
* 另外一种情况:如果主线程调用pthread_exit函数,则仅仅是主线程消亡,
* 进程不会结束,进程内的其他线程也不会终止,直到所有线程结束,进程才会结束;
* 线程终止最重要的问题是资源释放问题,特别是一些临界资源在一段时间内只能被
* 一个线程所持有,当线程要使用临界资源需提出请求,如果该资源未被使用则申请
* 成功,否则等待。临界资源使用完毕后要释放以便其它线程可以使用。
* 例如:某线程要写一个文件,在写文件时一般不允许其他线程也对该文件执行写操作的,
* 否则会导致文件数据混乱。这里的文件就是一种临界资源。临界资源为一个线程所独占,
* 当一个线程终止时,如果不释放其占有临界资源。则该资源会被认为还己经退出的线程所
* 独占,当一个线程终止时,如果不释放其占有的临界资源,则该资源会被认为还被认为还被
* 己经退出的线程所使用,因而永远不会得到释放。如果一个线程在等待使用这个临界资源
* 它就可能无限的等待下去,这就形成了死锁,而这往往是灾难性的。
* 为此提供了一对函数:
* pthread_cleanup_push(),pthread_cleanup_pop()用于自动释放资源。
* 从pthread_cleanup_push()的调用点到pthread_cleanup_pop()之间的程序段中的
* 终止动作(如调用pthread_exit)都将执行pthread_cleanup_push()所指定的清理函数。
*
* #include <pthread.h>
* #define pthread_cleanup_push(routine,arg)\
* {\
* struct _pthread_clean_buffer buffer;\
* _pthread_cleanup_push(&buffer,(routine),srg);
* #define pthread_cleanup_pop _pthread_cleanup_pop(&buffer,(exeute));}
* }
* 线程终止时另外一个要注意的问题是线程间的同步问题。一般情况下,进程中各个线程
* 的运行是相互独立的,线程的终止并不会相互通知,也不会影响其他线程,
* 终止的所点用的资源不会随着线程的终止而归还糸统,而是仍为线程所在的进程持有。
* 正如进程之间可以使用wait()糸统调用来等待其他进程结束一样,线程也有类似的函数
* pthread_join()函数
* #include <pthread.h>
* void pthread_exit(void *retval);
* int pthread_join(pthread_t th,void *thread_return);
* int pthread_detach(pthread_t th);
*
* 函数pthread_join用来等待一个线程的结束。
* @param pthread_t th 调用者将被挂起并等待th线程终止;
* @param void *thread_return 如果不为NULL 则*thread_return=retval.
* 需要注意的是一个线程仅允许一个纯种使用pthread_join()等待它的终止,
* 并且被等待的线程应该处于可join状态,即非DETACHED状态。
* DETACHED 状态是指对某个线程执行pthread_detach()后其所处的状态。
* 处于DETACHED判词的线程无法由pthread_join()同步。
* 一个join的线程所占用的内存公当有线程对其执行了pthread_join()后才会释放,因此为了
* 避免内存泄漏,所有线程的终止时,要么己被设为DETACHED,要么使用pthread_join()
* 来回收资源。(注意:一个线程不能被多个线程等待,否则第一个接收到信号的线程成功
* 返回,其余调用pthread_join()的线程返回错误代码ESRCH)
* @author MrClimb
* @version 1.1.0
* @date 2012-05-27
*/
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
/* *************************************************************** */
/**
* @Synopsis 主线程通过pthread_join等待辅助线程结束
* int pthread_create(pthread_t *thread,const pthread_attr_t *attr,
* void *(*start_toutine)(void *),void *arg);
* int pthread_join(pthread_t thread,void **retval);
*
* Compile and link with -pthread
* gcc demo1.c -g -Wall -lpthread
*/
/* *************************************************************** */
void * pthread_join_test(void *arg)
{
printf("我是线程,我来帮你分担一些事情!\n");
sleep(3);
pthread_exit(0);
return NULL;
}
void test1()
{
pthread_t pid;
int statuscode;
pthread_create(&pid,NULL,pthread_join_test,NULL);
pthread_join(pid,(void *)&statuscode);
printf("我退出进的状态码是: %d\n",statuscode);
}
/* *************************************************************** */
/**
* @Synopsis 终止同一进程的另一线程
* int pthread_cancel(pthread_t thread);
* int pthread_create(pthread_t *thread,const pthread_attr_t *attr,
* void *(*start_toutine)(void *),void *arg);
* int pthread_join(pthread_t thread,void **retval);
*
*/
/* *************************************************************** */
void * pthread_cancel_test(void *arg)
{
while(1){
printf("我正在工作中!\n");
sleep(1);
}
}
void test2()
{
pthread_t pid;
// int status=0;
void *status;
pthread_create(&pid,NULL,pthread_cancel_test,NULL);
sleep(3);
pthread_cancel(pid);
pthread_join(pid,&status);
// pthread_join(pid,NULL);
printf("终止进程状态码:%d\n",(int)status);
}
int main(int argc, char **argv)
{
#if 0
test1();
/**
* 结果分析:
* 从运行结果可以看出pthread_join会阻塞主线程,等待pthread_join_test结束。
* pthread_exit结束的退出码是0,pthread_join得出status 也为0,两者是一致的。
*/
#endif
#if 1
test2();
#endif
return 0;
}