多线程概念,线程控制


多线程

线程概念

进行多任务处理

多任务处理

多创建几个进程,一个进程就有一个pcb,能够串行化的完成一个任务,在一个进程创建多个pcb,因为pcb是调度程序运行的描述,因此有多少个pcb就会有多少个执行流程
在这里插入图片描述
多进程
在这里插入图片描述
多线程
在这里插入图片描述
最早的时候,进程就是一个pcb,操作系统通过pcb>实现调度管理;然而学习多线程,因为线程是进程中的一个执行流,并且这些pcb共用同一个虚拟地址,这些pcb更加轻量化,因此也被称为轻量级进程

在linux中,pcb就是调度程序运行的描述,一个pcb就可以调度一段程序的运行;
创建线程会伴随在内核中创建一个pcb来实现程序的调度,作为进程的一个执行流

进程就是多个线程的集合,并且这个进程中的所有pcb共用进程中的大部分资源(程序运行时,操作系统为程序所分配的所有资源)因此这些pcb在linux称为轻量级进程

线程间独有与共享
 独有:
栈,寄存器, 信号屏蔽字,errno,标识符,调度优先级
共有:虚拟地址空间,IO信息,信号处理方式,工作目录,用户ID/组ID

为什么信号是先注销在处理?
 信号针对整个经常通知时间进行处理的,但是一个信号只需要被处理一次就够了;然而一个进程有可能使用vfork创建一个子进程;父子进程共用一个虚拟地址空间,但父进程会阻塞直到子进程exit或重新替换;

多线程/多进程进行多任务处理的优缺点分析

多线程的优点

1.线程间通信更加灵活方便(处理进程间通信方式还有全局变量以及函数传参----共用一个虚拟地址空间,只要知道地址就能访问同一块空间)
 2.线程的创建与销毁成本更低(创建线程创建一个pcb,共用的数据只需要一个指针指向同一处就可以了)
 3.同一个进程中的线程间调度成本更低(调度切换需要切换页表…)

多进程的优点

1.多进程的健壮性,稳定性更高(异常以及一些系统调用exit直接针对整个进程生效)

共同的优点

 1.IO密集型程序:多任务并行处理
 2.CPU密集型程序:程序中进行大量的数据运算处理;cpu资源足够,就可以同时处理,提高效率(通常执行流的个数是cpu核心数+1),创建线程很多的话,而cpu资源不够多,会造成进程切换调度成本提高。

线程控制

通过代码实现线程的创建/ 退出/ 等待/ 分离

使用库函数创建一个线程,本质上是在内核中创建一个轻量级进程来实现程序的调度

线程的创建

int pthread_creat(pthread_t* thread, const 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> //sleep头文件
#include<string.h>  //字符串操作头文件
#include<pthread.h> //线程库接口头文件
void* thr_strat(void* arg){
     while(1){
        printf("nihaoya~%s\n", (char*)arg);
        sleep(1);
    }
    return NULL;
}
int main(){
    pthread_t tid;
    char ptr[] = "shuilme";
    int ret = pthread_create(&tid, NULL, thr_strat, (void*)ptr);
    if(ret != 0){
        printf("create thread failed!\n");
        return -1;
    }
    printf("create thread success!\n");
    while(1){
        printf("hello~\n");
        sleep(1);
    }
}

pcb是一个无符号长整型数据
一个线程就有一个pcb,每一个pcb都有一个pid----pcb是一个整型数据
tid和pid有什么联系
在这里插入图片描述
tid ----是一个线程id,线程的操作句柄,准确的来说这个tid就是用户态线程的id,这个id其实就是线程独有这块空间的首地址

每个线程被创建出来之后,都会开辟一块空间,存储自己的栈,自己的描述信息

pid----是一个轻量级进程id内核中的task_struct结构体中的id

task_struct->pid:轻量级进程id,也就是ps -ef看到的LWP

task_struct->tgid: 线程组id,等于主线程id(也就是外边看到的进程id)

线程的终止

如何退出一个线程

1. 线程入口函数运行完毕后,线程就会自动退出----在线程入口函数中调用return(但是main中调用return,退出的是进程还不是主线程)

2.
void pthread_exit(void* retval);退出线程接口- 谁调用谁退出,
retval是退出返回值(exit函数无论在哪个进程调用,退出的都是整个进程)
  主线程退出,并不会导致进程退出,只有所有的线程都退出了,进程才退出

3.
int pthread_cancel(pthread_t thread);终止一个线程;退出的线程是被动取消的

线程的等待

等待一个线程的退出,获取退出线程的返回值,回收线程所占的资源

线程有一个属性,默认创建出来这个属性是joinable,处于这个属性的线程,退出后,需要被其它线程获取返回值回收资源
int pthread_join(pthread_t thread, void **retval)----等待指定线程退出,获取返回值
参数列表:
thread:要等待退出的线程id
retval:输出型参数,用于返回线程的返回值

线程的分离

将线程joinable 属性改为detach 属性;
  一个线程属性若是joinable 那么就必须被等待
 一个线程属性若是detach那么这个线程退出后则自动释放资源,不需要被等待(因为资源已经自动释放了)
 分离一个线程,一定是你对线程的返回值,不感兴趣,根本就不想获取,又不想一直等待
int pthread_deatch(pthread_t thread);----将指定线程分离出去,属性改为detach

pthread_t pthread_self(void);返回调用线程的tid

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值