线程的终止方式

前几天对架构动了个小手术,居然因为一个线程的原因,在某个特殊情况下导致了core dump。虽然问题很快定位并解决,但还是决定把线程这块东西再捋一捋。今天就说下几种线程的终止方式。

说终止线程之前,顺道简单提一下地球程序员都知道的创建线程,这里只介绍Linux哈。

在Linux下,可通过pthread_create()创建一条新线程:
 

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

其中,pthread_t*类型的参数thread指向pthrad_t类型的缓冲区,在pthread_create()返回前,会在此保存一个该线程的唯一标识。
后续的Pthreads函数将使用该标识来引用此线程。

参数attr是一个指向pthread_attr_t类型对象的指针,该对象指定了新线程的各种属性,在实际应用中,多使用默认属性,即将该值设置为NULL。

start_routine()就是要执行的线程函数主体,arg是它的参数。arg是void*类型,意味着可以将任意对象的指针传递给start_routine函数。如果需要向start_routine传递多个参数,可将arg指向一个结构体,结构体中的各个字段对应于待传递的参数。

好了,线程创建好之后,怎么终止它呢?这里不考虑异常退出的情况,终止线程有如下几种方式:

1. 通过return的方式退出线程函数;
2. 线程调用pthread_exit()退出线程;
3. 调用pthread_cancel()取消线程;
4. 任意线程调用exit(),或main()函数执行return语句,会导致进程立即终止,当然,进程中的所有线程也将立即终止。

第1种方式就是函数的return,再简单不过,此处不赘述。

第2种方式跟第1种方式类似,也是线程内部退出的方式:pthread_exit(void* retval), retval指定了线程的返回值。pthread_exit()相当于在线程函数start_routine()中执行了return,不同的是,可在start_routine()函数所调用的任意函数中调用pthread_exit()。

第3种方式是从外部终止的方式,pthread_cancel()作用是向指定的线程发送一个取消请求。函数原型如下:

扫描二维码关注公众号,回复: 9405363 查看本文章
#include <pthread.h>

int pthread_cancel(pthread_t thread);   //Return 0 on success, or a positive error number on error

发出请求后,函数pthread_cancel()当即返回,不会等待目标线程的退出。一个简单的pthread_cancel的例子:

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>


static void* testFunc(void *arg)
{
	int i;
	
	printf("New thread started. \n");
	
	for(i = 0; ; i++)
	{
		printf("Loop %d\n", i);
		sleep(1);
	}
	
	return NULL;
}

int main(int argc, char *argv[])
{
	pthread_t thread_test;
	int s;
	void *res = NULL;
	
	s = pthread_create(&thread_test, NULL, testFunc, NULL);
	if(s != 0)
	{
		printf("pthread_create error! \n");
		return -1;
	}
	
	sleep(3);
	
	s = pthread_cancel(thread_test);
	if(s != 0)
	{
		printf("pthread_cancel error! \n");
		return -1;
	}
	
	
	s = pthread_join(thread_test, &res);
	if(s != 0)
	{
		printf("pthead_join error! \n");
		return -1;
	}
	
	if(res == PTHREAD_CANCELED)
	{
		printf("Thread is canceled. \n");
	}
	else
	{
		printf("Thread is failed to be canceled. \n");
	}
	
	return 0;
}

执行结果:

可见,线程的状态在pthread_join()中可以得到,上例中是保存在了第二个参数res里面。当然,thread_cancel还会涉及到取消点、资源清理等很多内容,时间关系,本篇先不展开。

最后提一下第4种线程终止方式,即在任何一个线程中调用exit(),导致整个进程终止,进程都退出了,线程自然也就终止了。这种也算是从外部终止线程的方式了。

发布了57 篇原创文章 · 获赞 58 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/DeliaPu/article/details/93777417