一、线程
1、定义
进程的创建、销毁与切换存在着较大的时空开销,因此人们急需一种轻型的进程技术来减少开销。在80年代,线程的概念开始出现,线程被设计成进程的一个执行路径,同一个进程中的线程共享进程的资源,因此系统对线程的调度所需的成本远远小于进程。
2、特性
①线程是一个基本的CPU执行单元,也是程序执行流的最小单位。
②每个线程都有一个线程TID、线程控制块(TCB)
③同一进程的不同线程间共享进程的资源
3、实现方式
4、线程与进程的区别
本质区别:进程是操作系统资源分配的基本单位,而线程是CPU任务调度和执行的基本单位。
包含关系:一个进程至少有一个线程,线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
资源开销:每个进程都有独立的地址空间,进程之间的切换会有较大的开销;线程可以看做轻量级的进程,同一个进程内的线程共享进程的地址空间,每个线程都有自己独立的运行栈和程序计数器,线程之间切换的开销小。
影响关系:一个进程崩溃后,在保护模式下其他进程不会被影响,但是一个线程崩溃可能导致整个进程被操作系统杀掉,所以多进程要比多线程健壮。
5、相关函数
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:用于存储新创建的线程的标识符(tid)
const pthread_attr_t *attr:指向线程属性对象的指针,设置为 NULL 以使用默认属性
void *(*start_routine) (void *):指向线程函数的指针,这个线程函数是线程开始执行时调用的函数(线程处理函数),线程处理函数的名字:void *pthread_task(void *arg)
void *arg:传递给线程处理函数的参数,这个参数的值将被传递给 start_routine 函数
函数返回值:
成功 返回0
失败 返回-1
注意:当你声明一个 pthread_t 类型的变量时,你实际上是在为该线程分配一个标识符(tid),但这个标识符本身在声明时并不会被自动初始化或分配给一个实际的线程
示例1:利用pthread_create函数,创建一个子线程,观察一下。
现象:
代码:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <pthread.h>
//线程处理函数
void *pthread_task(void *arg)
{
printf("hello_world\r\n");
}
int main(int argc,char* argv[])
{
//生成线程的标识符
pthread_t tid;
int ret;
//创建线程
ret = pthread_create(&tid,NULL, pthread_task, NULL);
if(ret == 0)
{
printf("pthread create success\r\n");
}
//输出一下tid
printf("tid:%ld\r\n",tid);
while(1);
return 0;
}
示例2:利用pthread_create函数,将对应的参数(数字),传递给对应的线程处理函数。
现象:
代码:
include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <pthread.h>
//线程处理函数
void *pthread_task(void *arg)
{
//输出对应的arg long --类型
long a=(long)arg;
printf("a=%ld\r\n",a);
printf("task%ld=hello\r\n",a);
}
int main(int argc,char* argv[])
{
//生成线程的标识符
pthread_t tid;
int ret;
//创建线程
ret = pthread_create(&tid,NULL, pthread_task, (void *)1);
if(ret == 0)
{
printf("pthread create success\r\n");
}
printf("tid:%ld\r\n",tid);
while(1);
return 0;
}
示例3:利用pthread_create函数,将对应的参数,传递给对应的线程处理函数。-传递参数是变量
现象:
代码:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <pthread.h>
//线程处理函数
void *pthread_task(void *arg)
{
//输出对应的arg long --类型
int a=*(int*)arg;
printf("a=%d\r\n",a);
printf("task%d=hello\r\n",a);
}
int main(int argc,char* argv[])
{
//生成线程的标识符
pthread_t tid;
int ret;
//定义变量
int a = 10;
//创建线程
ret = pthread_create(&tid,NULL, pthread_task, (void *)&a);
if(ret == 0)
{
printf("pthread create success\r\n");
}
printf("tid:%ld\r\n",tid);
while(1);
return 0;
}
示例4:利用pthread_create函数,传递一个结构体,观察一下
现象:
代码:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <pthread.h>
//声明一个结构体
struct test{
int test1;
char test2;
};
//线程处理函数
void *pthread_task(void *arg)
{
//输出对应的arg long --类型
struct test* a=(struct test*)arg;
printf("test1=%d\r\n",a->test1);
printf("test2=%c\r\n",a->test2);
printf("task%d=hello\r\n",a->test1);
}
int main(int argc,char* argv[])
{
//生成线程的标识符
pthread_t tid;
int ret;
//定义结构体变量
struct test a={10,'c'};
//创建线程
ret = pthread_create(&tid,NULL, pthread_task, (void *)&a);
if(ret == 0)
{
printf("pthread create success\r\n");
}
printf("tid:%ld\r\n",tid);
while(1);
return 0;
}
pthread_exit
函数功能:
退出当前的一个线程
头文件:
#include <pthread.h>
函数原型: