首页 > 技术文章 > 线程控制1

area-h-p 2019-09-25 16:14 原文

1.线程创建函数

#include<pthread.h>
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void*(*start_routine)(void*), void *arg);

参数解析

thread:当线程创建成功返回创建线程ID;

attr:指定线程的属性,大多使用NULL表示默认属性

start_routine:函数指针,指向线程创建后要调用的函数。被调用的线程函数也被称为线程函数。

arg:该参数指向传递给线程函数的参数。

注:线程创建成功时,函数会返回0,若返回值不为0则说明线程创建失败。

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
int thread(void *arg)
{
	printf("how to use pthread_create function %d \n", pthread_self());
	return 0;
}
int main()
{
	pthread_t th;
     printf("main function pthread num is %ld \n", pthread_self());
if(pthread_create(&th, NULL,(void*)thread, NULL) != 0) { printf("create pthread failed\n"); exit(1); } sleep(1); return 0; }

 运行一下

为啥gcc后边要加 -lpthread呢?

原因是pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a,所以在使用pthread_create()创建线程,以及调用 pthread_atfork()函数建立fork处理程序时,需要链接该库。

看着就像是主程序叫了一个小弟帮他干活,仿佛和主函数调用函数一样,但事实并不是这样。将倒数第二行代码去掉以后会发现线程函数thread并不会被执行,因为主线程结束了则整个进程截止了,此时进程中的所有线程也也将终止,这也是线程和普通函数调用的一大区别。

注:pthread_self()函数即为获取线程号的函数。

2.线程终止

Linux有两种方式可以使线程终止。一种通过return从线程函数返回,另一种是使用pthread_exit()函数退出线程。

这里有两种情况需要注意:

一个情况是上面刚刚提到的main函数返回或者使用了exit函数退出主进程,则进程内所有线程也将终止。

另一个情况是如果只是主线程调用了pthread_exit()函数,仅仅是主线程死亡,进程不会结束,而且在主线程内创建的其他线程也不会被终止,直到所有线程结束,进程才会结束。

例如:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
int thread1(void *arg)
{
	printf("2. how to use pthread_create function %ld \n", pthread_self());
	return 0;
}
int thread(void *arg)
{
	pthread_t th;
	printf("1. how to use pthread_create function %ld \n", pthread_self());
	if(pthread_create(&th, NULL, (void*)thread1, NULL) != 0)
	{
		printf("create pthread failed\n");
		exit(1);
	}
	pthread_exit(1);
}
void main()
{
	pthread_t th;
	printf("main function pthread num is %ld \n", pthread_self());
	if(pthread_create(&th, NULL,(void*)thread, NULL) != 0)
	{
		printf("create pthread failed\n");
		exit(1);
	}
	pthread_exit(1);
}

 运行结果

 

 这次主程序并没有挂起来等待线程,而是在最后使用pthread_exit()退出,其他子线程并没受到影响。

在线程中,也有和和进程中的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);

 函数ptread_join用来等待一个线程的结束。pthread_join()的调用者将被挂起等待线程号为th的线程终止,如果th线程退出使用了pthread_exit(),则*thread_return = retval。

注意:一个线程仅能允许被一个线程使用pthread_exit()等待它的终止·,并且被等待的线程应该处于可join状态,不可以为DETACHED状态。DETACHED状态是指某个线程执行pthread_detach()后其所处的状态。处于DETACHED状态的线程无法由pthread_join()同步。

一个可“join”的线程所占用的内存仅当有线程对其执行了pthread_join()后才会释放,因此为避免内存泄漏,所有线程的终止时,要么被设为DETACHED,要么使用pthread_join回收资源。

 例程

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
void test(void *arg)
{
	printf("T am helping me to understand what's pthread_join\n");
	sleep(5);
	pthread_exit(6);
}
int main()
{
	pthread_t ts;
	int status;
	pthread_create(&ts, NULL,(void*)test, NULL);
	pthread_join(ts, (void*)&status);
	printf("test's exit is cause %d\n", status);
	return 0;
}

 运行结果

 

 “test's exit is cause 6”这句活在上一句打印后约5秒才被打印出来,说明调用pthread_join的线程的确会被挂起等待要等的线程结束才会继续运行。

推荐阅读