多线程笔记

多线程:线程概念,线程控制,线程安全,线程应用

线程概念:

线程就是进程中的一条执行流,是cpu调度执行的基本单元

而linux下的线程是通过pcb实现的,一个进程可以有多个pcb,这些pcb共享了进程的大部分资源,相较

线程之间的独有与共享

共享资源:虚拟地址空间,文件描述表,信号的处理方式,工作路径,用户ID,组ID...

独有资源:标识符,栈,上下文数据,信号屏蔽字,errno...

于传统的pcb较为轻量,因此也被称作轻量级进程

进程与线程的区别:

进程是系统进行资源分配的基本单位,而线程是CPU调度执行的基本单元

在多任务处理中,多进程与多线程各有优缺点

       多进程:健壮性,稳定性高

       多线程:1.线程间的通信更加灵活

                      2.线程的创建与销毁成本更低

                      3.同一个进程的线程间切换调度成本更低

在使用中,如果对主程序的要求特别高,比如服务器,Shell的程序,就适用于多进程,其他基本都是多线程

在多任务处理中,使用多执行流完成的优点:更加充分的利用计算机资源,提高任务处理效率

在多任务处理中启动多少执行流比较合适?

执行流并不是越多越好,因为执行流越多,CPU切换调度就越频繁,如果执行流太多,返回会造成切换调度消耗了大部分资源

在任务处理中,程序分为2种:

1. cpu密集型程序: 一段程序中几乎都是数据的运算(对cpu的使用率非常高)

2.IO密集型程序:一段程序中大部分都是IO操作(大部分时间都是在进行IO操作以及等待,因此对CPU的使用率不高)

因此,不同的程序对于CPU的要求是不一样的,多执行流没有什么固定的数量,最好是通过压力测试找到最合适的数量。

线程控制:

主要讲线程的操作接口(创建,终止,等待,分离)

linux下线程的操作接口,其实都是库函数,因此linux操作系统并没有直接向上层提供线程的系统调用接口,因此基于系统调用的接口封装实现了线程的相关接口。

创建:

int pthread_create(pthread_t *tid,pthread_attr_t *attr, void* (*routine)(void*), void *arg

tid:传入一个pthrea_t类型变量的空间地址,用于接收线程ID--线程的操作句柄

attr:线程属性--大部分的属性其实不用管,后面有一个分离属性使用单独接口进行设置,因此这里的属性通常置NULL

routine:函数指针,传入线程入口函数的地址,这个线程调度运行的就是这个函数

arg:给routine线程入口函数传入的参数

功能:创建一个线程,指定这个线程要运行的函数routine,并且给这个函数传入一个数据arg

返回值:成功返回0;失败返回非0值

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>4
void*thread_entry(void*arg){
    while(1){
        printf("i am child thread:%s\n",arg);
    }
        return NULL;
}
int main(){
// int pthread_create(pthread_t *tid, pthread_attr_t *attr,void*(*routine)(void*), void*ang)
        pthread_t tid;
        char*arg-"lelihoua~!!";
        int ret=pthread_create(&tid,NJLL,thread_entry,(void*)arg);
    if(ret!=0){
        printf("pthread create error!\n");
        return-1;
    }//普通线程一旦创建成功了,创建出来的这个线程调度的是传入的线程入口函数,因此能够走下来的只有主线程
    while(1){
        printf("i am main thread!!\n");
    }
   heturn 0;
}

线程被创建出来后,谁先运行不一定,取决与操作系统的调度

创建一个线程,其实是操作系统提供一个执行流,至于这个线程做什么,取决于线程的入口函数,而线程的入口函数由程序员定

注意:线程只是一个执行流,线程是调度一个函数运行的

线程信息的查看:ps-L选项进行查看(查看其实是轻量级进程信息)

在多线程程序中,一个进程里边有多个pcb,当ps查看进程信息的时候显示什么?

一个进程运行起来,默认就会创建一个线程(pcb),这个线程有自己的pid

如果下边通过pthread_create创建了一个线程(pcb),这个线程也有自己的pid

真正使用ps查看进程信息的时候查看的是主线程pcb对应的信息

线程终止:如果退出一个线程

1.在线程入口函数中return;

  注意:main中的return退出的不仅仅是主线程,而是整个进程

2.在任意位置调用接口:void pthread_exit(void *retval);

    retval:用于设置线程的退出返回值

    上面两种方式都是主动退出,在线程的任意位置主动调用,主动退出,谁调用,谁退出

3.在任意位置调用接口:void pthread_cancel(pthread_t tid);

   注意:这个接口是用来取消指定线程运行的

              一个线程如果是被取消的,则他的返回值就不是一个正经的返回值了

等待与分离

1.主线程退出,不会影响其他进程的运行(通常不多见)

所有的线程退出了,则进程退出释放所有资源;如果进程要退出,则会先退出所有的进程

2.一个线程推出了,资源也并没有完全被释放(因为要保存返回值)

僵尸进程:子进程退出了,为了保存退出码,因此没有直接释放资源,等待父进程处理

等待:等待指定的进程退出,获取退出线程的返回值,回收退出线程的所有资源

     int pthread_join(pthread_t tid, void **retval);

tid:是要等待退出的指定的线程的tid

retval:用于获取线程的退出返回值;(因为线程的退出返回值是void*,因此传入指针变量的地址,将地址放入到指针变量空间)返回值:成功返回O;失败返回一个错误编号

线程之间传递数据需要尤其注意数据的生命周期

如果一个线程是被取消的,则获取的到的返回值是PTHREAD_CANCELED本质是个(void*)-1

分离:

在线程属性中,有一个属性叫做分离属性,默认值是joinable状态,表示线程退出后,不会自动释放资源,需要被其他线程等待

但是有时候我们并不关心一个线程的返回值,也不想等待他的退出,则这时候将这个分离属性设置为detach状态

detach状态:表示线程退出后,自动释放所有资源,不需要被等待(资源是自动释放的,因此也不能被等待--等待会出错)

接口:

int pthread_detach(pthread_t tid);   //设置指定线程的分离属性为detach

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值