一,线程创建
1.1 每一个线程都有一个唯一的线程ID,ID类型为pthread_t,这个ID是一个无符号长整形数,如果想要得到当前线程的线程ID,可以调用如下函数:
pthread_t pthread_self(void); // 返回当前线程的线程ID
1.2线程创建
**#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void ), void arg);
参数
thread: 传出参数,是无符号长整形数,线程创建成功, 会将线程ID写入到这个指针指向的内存中
attr: 线程的属性, 一般情况下使用默认属性即可, 写NULL
start_routine: 函数指针,创建出的子线程的处理动作,也就是该函数在子线程中执行。
arg: 作为实参传递到 start_routine 指针指向的函数内部
返回值:线程创建成功返回0,创建失败返回对应的错误号
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
// 子线程的处理代码
void* working(void* arg)
{
printf("我是子线程, 线程ID: %ld\n", pthread_self());
for(int i=0; i<9; ++i)
{
printf("child == i: = %d\n", i);
}
return NULL;
}
int main()
{
// 1. 创建一个子线程
pthread_t tid;
pthread_create(&tid, NULL, working, NULL);
printf("子线程创建成功, 线程ID: %ld\n", tid);
// 2. 子线程不会执行下边的代码, 主线程执行,
printf("我是主线程, 线程ID: %ld\n", pthread_self());
for(int i=0; i<3; ++i)
{
printf("i = %d\n", i);
}
return 0;
}
程序分析: 在main函数里面创建出子线程之后,子线程就开始和主线程抢夺资源(这取决于操作系统对线程的优先级管理),程序运行就有随机性,可能主线程运行完之前就被抢占了CPU,即i=2之前就被进入子线程处理函数(即子线程抢到了CPU,子线程完成之后,驻主线程重新拿到CPU控制权。也有可能是主线程执行完毕,子线程没有抢到CPU
随机情况1
随机情况2
二,线程退出
在编写多线程程序的时候,如果想要让线程退出,但是不会导致虚拟地址空间的释放(针对于主线程),我们就可以调用线程库中的线程退出函数,只要调用该函数当前线程就马上退出了,并且不会影响到其他线程的正常运行,不管是在子线程或者主线程中都可以使用。
#include <pthread.h>
void pthread_exit(void *retval);
参数
线程退出的时候携带的数据,当前子线程的主线程会得到该数据。如果不需要使用,指定为NULL
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
// 子线程的处理代码
void* working(void* arg)
{
sleep(1);
printf("我是子线程, 线程ID: %ld\n", pthread_self());
for(int i=0; i<9; ++i)
{
if(i==6)
{
pthread_exit(NULL); // 直接退出子线程
}
printf("child == i: = %d\n", i);
}
return NULL;
}
int main()
{
// 1. 创建一个子线程
pthread_t tid;
pthread_create(&tid, NULL, working, NULL);
printf("子线程创建成功, 线程ID: %ld\n", tid);
// 2. 子线程不会执行下边的代码, 主线程执行
printf("我是主线程, 线程ID: %ld\n", pthread_self());
for(int i=0; i<3; ++i)
{
printf("i = %d\n", i);
}
// 主线程调用退出函数退出, 地址空间不会被释放
pthread_exit(NULL);
return 0;
}
程序分析: 在main函数里面创建出子线程之后,子线程就开始和主线程抢夺资源(这取决于操作系统对线程的优先级管理),主线程运行完之前就被抢占了CPU,即i=2之前就被进入子线程处理函数(即子线程抢到了CPU,子线程完成之后,主线程重新拿到CPU控制权。也有可能是主线程执行完毕,子线程没有抢到CPU ,但是由于使用线程推出函数不会释放虚拟可见,所以子线程一定可以执行完毕