所有API的头文件
#include<pthread.h>
1、创建
函数原型
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// 返回:若成功返回0,否则返回错误编号
当pthread_create成功返回时
tidp:指向的内存单元被设置为新创建线程的线程ID。
attr:用于定制各种不同的线程属性,设置为NULL就是创建默认属性的线程。
start_rtn: 新创建的线程从start_rtn函数的地址开始运行,只有一个无类型指针参数arg。
arg:向start_rtn函数传递的参数,如果不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为第四个参数arg传入。
2、等待
函数原型
int pthread_join(pthread_t thread, void **rval_ptr);
// 成功返回0,否则返回错误编号
thread:线程名
**rval_ptr :线程返回值
调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、如果例程只是从它的启动例程返回,rval_ptr将包含返回码。如果线程被取消,由rval_ptr指定的内存单元就置为PTHREAD_CANCELED。
如果线程的返回值不重要,可以把rval_ptr设置为NULL。再调用pthread_join函数时,将等待指定的线程终止,但并不获得线程的终止状态。
3、退出
线程退出方式有三种(不终止整个进程的情况)
1)线程从启动例程中返回,返回值是线程的退出码。
2)线程可以被同一进程中的其他线程取消。
3)线程调用pthread_exit函数。
pthread_exit函数原型
int pthread_exit(void *rval_ptr);
rval_ptr是一个无类型指针,与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针。
其他API
4、线程脱离
一个线程或者是可汇合(joinable,默认值),或者是脱离的(detached)。当一个可汇合的线程终止时,它的线程ID和退出状态将留存到另一个线程对它调用pthread_join。
pthread_detach函数把指定的线程转变为脱离状态。
函数原型
int pthread_detach(pthread_t thread);
// 返回:若成功返回0,否则返回错误编号
函数想让自己脱离的线程使用,就如以下语句:
int pthread_detach(pthread_self());
返回值: 成功返回0,否则返回错误编号
5. 线程ID获取
函数原型
pthread_t pthread_self(void);
返回值: 调用线程的ID
6、线程比较
对于线程ID比较,为了可移植操作,不能简单地把线程ID当作整数来处理,因为不同系统对线程ID的定义可能不一样。应该要下边的函数:
函数原型:
int pthread_equal(pthread_t tid1, pthread_t tid2);
返回值: 若相等则返回非0值,否则返回0
tid1,tid2:线程名字
示例代码
当线程退出值为整数时
#include <stdio.h>
#include <pthread.h>
void *func(void *arg)
{
static int ret = 10; //定义变量,注意为static类型
printf("t1 id = %ld thread is create\n",(unsigned long)pthread_self());//打印t1线程id
printf("t1 param is %d\n",*((int *)arg)); //将main线程传递的数据打印出来
pthread_exit((void *)&ret); //线程退出,10为退出码
}
int main()
{
int ret;
int param = 100;
int *pret = NULL;
pthread_t t1; //创建t1线程
ret = pthread_create(&t1,NULL,func,(void *)¶m);//如果有多个数据时,建立一个结构体param
if(ret == 0){
printf("main create t1 success\n");
}
printf("main = %ld\n",(unsigned long)pthread_self()); //打印main线程id
// sleep(5); //等待线程执行完
// pthread_join(t1,NULL); //等待线程退出,不收集退出信息
pthread_join(t1,(void **)&pret); //将退出信息放入到指针pret中
printf("main t1 quit is %d\n",*pret); //打印退出信息
return 0;
}
运行结果
当线程退出值为字符串时
#include <stdio.h>
#include <pthread.h>
void *func(void *arg)
{
static char *pret = "hello world";//定义变量,注意为static类型
printf("t1 id = %ld thread is create\n",(unsigned long)pthread_self());//打印t1线程id
printf("t1 param is %d\n",*((int *)arg)); //将main线程传递的数据打印出来
pthread_exit((void *)pret); //线程退出,10为退出码
}
int main()
{
int ret;
int param = 100;
char *pret = NULL;
pthread_t t1; //创建t1线程
ret = pthread_create(&t1,NULL,func,(void *)¶m);//如果有多个数据时,建立一个结构体param
if(ret == 0){
printf("main create t1 success\n");
}
printf("main = %ld\n",(unsigned long)pthread_self()); //打印main线程id
// sleep(5); //等待线程执行完
// pthread_join(t1,NULL); //等待线程退出,不收集退出信息
pthread_join(t1,(void **)&pret); //将退出信息放入到指针pret中
printf("main t1 quit is %s\n",pret); //打印退出信息
return 0;
}
运行结果
线程共享内存的验证
#include <stdio.h>
#include <pthread.h>
int p_data = 0;
void *func1(void *arg)
{
printf("t1 param is %d\n",*((int *)arg));//main传递的数据
while(1){
printf("t1 p_data : %d\n",p_data++);//打印全局变量p_data
sleep(1); //睡眠1s
}
}
void *func2(void *arg)
{
printf("t2 param is %d\n",*((int *)arg));//main函数传递的值
while(1){
printf("t2 p_data : %d\n",p_data++); //打印全局变量
sleep(1); //睡眠1s
}
}
int main()
{
int ret;
int param = 100; //传递的数据
pthread_t t1; //线程一
pthread_t t2; //线程二
ret = pthread_create(&t1,NULL,func1,(void *)¶m); //创建线程一
if(ret == 0){
printf("main create t1 success\n");
}
ret = pthread_create(&t2,NULL,func2,(void *)¶m); //创建线程二
if(ret == 0){
printf("main create t2 success\n");
}
while(1){
printf("main p_data : %d\n",p_data++); //全局变量在main函数中的值
sleep(1);
}
pthread_join(t1,NULL); //等待线程一退出
pthread_join(t2,NULL); //等待线程二退出
return 0;
}
运行结果
可以看到 p_data 在任意一个线程中改变值,都会影响其他线程 p_data 的值,也就是同一进程下的线程的内存是共享的。