头文件:#include<pthread.h>
1、创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void* (*start_routine)(void *), void *arg))
功能:创建一个线程。
参数:
参数1:是一个传出参数,用于保存成功创建线程之后对应的线程id。
参数2:表示线程的属性,通常默认传NULL,如果想使用具体的属性也可以修改具体的参数。
参数3:函数指针,一个指向函数的指针。指向创建线程所执行函数的入口地址,函数执行完毕,则线程结束。
参数4:线程主函数执行期间所使用的参数。通常是NULL
返回值:成功创建返回值为0,错误返回错误号。注意:由于创建线程函数是一个库函数,不是系统调用函数。所以其错误信息不能用perror()进行打印,采用strerror(错误号)
可以将错误信息打印出来。其中strerror
函数是包含#include<string.h>
之中的一个库函数。
示例:
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<sys/types.h>
void* my_fun(void *arg)
{
while(1)
{
printf("我是子线程\n");
sleep(1);
}
}
int main()
{
pthread_t pthid;//传出参数,保存创建成功后的线程id
int res = pthread_create(&pthid,NULL,my_fun,NULL);
//参数2默认为NULL,指的是线程的属性
//函数指针,指向创建出线程的主函数
//线程主函数的参数,就是void* my_fun(void *arg)中的void *arg
if(res != 0)
{
printf("%s\n",strerror(res));//打印错误信息
}
printf("我是父线程\n");
//由于程序执行的速度非常快,子线程还没来得及执行。进程已经结束
//主线程睡眠两秒,使得子线程可以执行完毕
sleep(2);
return 0;
}
2、获取线程id
函数原型:pthred_t pthread_self(void);
功能:获取当前线程的id。
参数:无参。
返回值:返回值为一个无符号长整型。(#define pthread_t unsigned long int)
说明:线程id是在一个进程中的内部标识,但不同进程中的线程id可能相同
示例:
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<pthread.h>
void* fun(void *arg)
{
printf("子线程id:%lu\n",pthread_self());
return NULL;
}
int main()
{
pthread_t pthid;
int res = pthread_create(&pthid,NULL,fun,NULL);
if(res != 0)
{
printf("%s\n",strerror(res));
}
printf("主线程id:%lu\n",pthread_self());
sleep(1);
return 0;
}
注意:在使用gcc进行编译的时候需要加库名,否则会出先链接错误。因为线程库头文件仅仅包含了函数的声明,函数的实现在哪里编译器是不知道。如果不加库名,会出现如下的链接错误。 (-lpthread)
线程的退出
- exit, _Exit, _exit用于中止当前进程,而非线程
- 中止线程可以有三种方式:
a. 在线程函数中return
b. 被同一进程中的另外的线程Cancel掉
c. 线程调用pthread_exit函数