多线程:包括线程概念/线程控制/线程安全/线程基本应用

多任务处理:多创建几个进程,一个进程就有一个pcb,能够串行化的完成一个任务,在一个进程中多创建几个pcb,pcb是调度程序运行的描述,有多少个pcb就有多少个执行流程,

什么是线程?

线程是一个进程内部的控制序列,线程是进程中的一条执行流,在linux下通过pcb实现,因此实际上linux下的线程就是一个pcb,并且linux下的pcb共用一个虚拟地址空间,相较于传统pcb更加轻量化,也被称之为轻量级进程。

多线程是同时处理,只有一个虚拟地址空间,多进程各有各的虚拟地址空间和执行代码段。

进程是操作系统资源分配的基本单位;(操作系统会为一个程序的运行分配所需的所有资源)

线程是cpu调度的基本单位。

linux下的进程其实是一个线程组,一个进程中可以有多个线程(多个pcb),线程是进程中的一条执行流。一个进程中至少会有一个线程。

创建线程会伴随在内核中创建一个pcb来实现程序的调度,作为进程中的一条执行流。

进程就是多个线程的一个合集,并且这个进程中的所有pcb共用进程中的大部分资源(程序运行时,操作系统为程序运行所分配的所有资源)。

线程之间的独有与共享:

独有:标识符,寄存器,信号屏蔽字,优先级。

共享:虚拟地址空间(代码段/数据段),文件描述符表(IO信息),信号处理的回调函数(SIG_IGN忽略、SIG_DFL默认或自定义),当前工作目录,用户id和组id。

为什么信号是先注销,再处理?

信号时针对整个进程通知事件进行处理的,但是一个信号只需要被处理一次就够了,然而一个进程会有多个执行流,到底谁处理这个事件(谁拿到时间片,谁就能处理),有的线程不希望操作被打断,就可以屏蔽这个信号。

使用vfork创建一个子进程;父子进程共用同一个虚拟地址空间,但是父进程会阻塞(父进程阻塞的原因是防止调用栈紊乱,数据紊乱)直到子进程exit或者程序替换;

fork(写时拷贝,修改的时候开辟空间)不仅会创建pcb还会为pcb创建虚拟地址空间,创建页表,因此fork后父子进程数据独有(各有各的虚拟地址空间,若数据发生改变映射后指向不同的物理内存区域),代码共享的。

fork完虚拟地址空间是立即创建的,物理内存没有立即创建,而是数据发生改变时(是改变页表映射)才会重新开辟,拷贝数据过来。

创建线程是创建一个pcb,然后通过指针指向同一个虚拟地址空间,映射的也是同一块物理内存。

多线程:多个pcb作为独立执行流肯定是同时运行,如何做到不会调用栈混乱

errno:系统调用完毕后重置的一个全局变量。

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

多线程的优点:

1.线程间通信更加灵活方便(除了进程间通信方式之外还有全局变量以及函数传参)--共用同一个虚拟地址空间,只要知道地址就能访问同一块空间)

2.线程的创建与销毁成本更低(创建线程创建一个pcb,共用的数据只需要使用一个指针指向同一处就可以)

3.同一个进程中的线程间调度成本更低(调度切换需要切换页表...)

多进程的优点:

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

共同的优点:等待+数据拷贝

1.IO密集型程序:多任务并行处理,对cpu要求并不高,执行流个数没有要求(多磁盘可以实现同时处理)

2.CPU密集型程序:程序中进行大量数据运算处理;cpu资源足够,就可以同时处理,提高效率                                    (通常执行流的个数是cpu核心数+1)

创建线程很多的话,而cpu资源不够多,会造成大量的进程切换调度成本提高

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

线程控制的代码都是库函数,有封装的线程库函数。使用库函数创建一个线程,本质是在内核中创建一个轻量级进程实现程序调度。

线程创建-创建一个新的线程:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *
(*start_routine)(void*), void *arg);

thread:输出型参数,用于获取线程ID--线程的操作句柄
    attr:设置线程的属性,attr为NULL表示使用默认属性
    start_routine:是个函数指针,线程启动后要执行的函数,运行完毕,线程退出
    arg: 传给线程启动函数的参数
    返回值:成功返回0;失败返回错误码(非0)

声明和定义的区别就是有无实现。

未声明:不知道这个函数或变量,从来没有。(通常是没有添加头文件)

未定义:只是不知道这个函数或变量的空间和实现在哪里。(没有把库添加上)

线程创建代码如下:

tid是一个无符号长整形数据,一个线程就有一个pcb,每个pcb都有一个pid--pid是一个整形数据。

tid和pid有什么联系?

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

 tid---是一个线程id,线程的操作句柄,这个tid是用户态线程的id是线程独有的这块空间的首地址,每个线程被创建出来之后,都会开辟一块空间,存储自己的栈,自己的描述信息。

ps -ef|grep create 看到的进程信息中的pid到底是哪个pcb的pid?

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

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

LWP和tgid实际上几乎用不到,因为线程的操作都是通过tid完成的。

结果如下:

库的链接使用:

whereis libpthread.so可以查看库的位置。

1.将库文件放在指定的路径下 /lib64    /usr/lib64

2.将库文件路径添加到环境变量  LIBRARY_PATH中。

3.使用gcc -L选项指定库文件所在路径。

4.gcc默认链接动态库,动态库也可以使用-L指定库路径,-l指定库名称

线程终止--线程退出--如何退出一个线程?

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

结果可以看到普通线程只运行了一次 就退出,而主线程没有退出。

void pthread_exit(void *retval); 退出线程接口--谁调用谁退出,retval是退出返回值。

但是exit无论在哪都是进程退出。
代码如下:

结果如下:

发现主线程退出了,普通线程还依然在打印。通过查看进程发现,有2个exit,第一个为僵尸状态-僵尸进程,第二个为休眠状态。

主线程退出,并不会导致进程退出,只有所有的线程都退出了,进程才会退出。

int pthread_cancel(pthread_t thread);取消一个线程;退出的线程被动取消的。

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

线程有一个属性,默认创建出来这个属性是joinable,处于这个属性的线程,退出后,需要被其他线程等待获取返回值回收资源。

int pthread_join(pthread_t thread, void **retval);--等待指定线程退出,获取其返回值

thread:要等待退出的线程tid

retval:输出型参数,用于返回线程的返回值。
线程的返回值是一个void*,是一个一级指针。若要通过一个函数的参数获取一级指针,就需要传入一个一级指针变量的地址进来。

常量与普通变量的区别--存储位置不同,生命周期不同

默认情况下,一个线程必须被等待,若不等待,则会造成资源泄露。

线程分离:将线程joinable属性修改为detach属性

一个线程属性若是joinable那么就必须被等待

一个线程属性若是detach那么这个线程退出后则自动释放资源,不需要被等待(因为资源已经自动被释放了)

为什么要分离线程?

分离一个线程,一定是对线程的返回值不感兴趣,根本不想获取,又不想一直等待线程退出,这种情况才会分离线程。

int pthread_detach(pthread_t thread);--将指定的线程分离出去--属性修改为detach

pthread_detach(pthread_self());--返回调用线程的tid,自己分离自己,实际就是设置一个属性。

分离线程,只是说线程退出后自动释放资源。

linux下的多线程相关推荐

  1. Linux下的多线程编程

    1 引言 线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者.传统的Unix也支持线程的概念,但是在一个进程(process ...

  2. [原创]手把手教你Linux下的多线程设计--Linux下多线程编程详解(一)

    本文可任意转载,但必须注明作者和出处. [原创]手把手教你Linux下的多线程设计(一)                                       --Linux下多线程编程详解 原 ...

  3. Linux下实现多线程的生产者消费者问题

    Linux下实现多线程的生产者消费者问题 一.原理的理解 生产者-消费者问题是一个经典的线程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制.在同一个线程地址空间内执行的两个线程 ...

  4. Linux下不使用qt自带sleep,Linux下Qt多线程编程

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 作者:武汉华嵌嵌入式培训中心 技术部 以下和大家分享Linux平台下Qt两种多线程编程的方式: 1.使用Linux平台下的线程函数.以下是给出的代码片段: ...

  5. linux 下的 多线程http 下载器

    Linux下多线程下载工具-Axel Axel是命令行下的多线程下载工具,支持断点续传,速度通常情况下是Wget的几倍. 它的官方网站: http://wilmer.gaa.st/main.php/a ...

  6. linux下串口多线程通信 ,多串口收发数据错乱问题解决办法

    最近在写AM335x平台的串口测试工具,最开始的时候写的第一版本,测试一直很ok,但是存在一些缺陷,于是就想改进一下,没想到后面在新的板子测试,竟然发现了以个很致命的问题,在旧系统旧内核测试一切正常, ...

  7. Linux下实现多线程异步管道

    目录 架构 代码 相关阅读 ​"最近在做F-Stack相关内容,F-Stack协议栈单线程独占异步轮询网卡,所以要求异步​.但是又有多线程需要利用F-Stack进行发包,并且发包ff_sen ...

  8. Linux下的多线程編程

    Linux下的多線程編程 本文出自:http://www.china-pub.com 引言 線程(thread)技術早在60年代就被提出,但真正應用多線程到操作系統中去,是在80年代中期,solari ...

  9. linux 中多进程下载工具,[转载]Linux 下安装多线程下载工具 proz

    学习Linux,就不停的要到网上下载各种各样的源码包或rpm包,只在图形界面下操作,如果网络不是很流畅(比如我的adsl)通常很慢,而且不稳定,有时候会出现下载包不完整的情况,所以建议找个下载工具装上 ...

最新文章

  1. pandas计算滑动窗口中的中位数实战(Rolling Median of a Pandas Column):计算单数据列滑动窗口中的中位数、计算多数据列滑动窗口中的中位数
  2. android 日历按周获取,Android日历获取当前周,前几周和下周
  3. Boost.Asio技术文档汇总
  4. android attrs获取_Android 常用侧滑栏实现
  5. 记录用NoteExpress下载文献全文成功
  6. .jks或者.keystore文件查看MD5、SHA-1和SHA-256
  7. 线性回归相关系数c语言,线性回归中的相关系数;
  8. 单片机控制的双路有源滤波器设计
  9. mysql启动黑屏_红警win10黑屏和不显示菜单栏问题 只有声音没有图像的解决
  10. Python获取图片保存对应的文件夹
  11. UTI ( Uniform Type Identifier )
  12. 计算机安全概述ppt,计算机信息安全概述.ppt
  13. Android app界面设计工具AppInventor初体验
  14. 还不到4折:赶紧来抢券啊!!!
  15. 如何去除图片背景颜色?怎样将背景色变透明?
  16. 正确理解和判断PR劫持的方法(站长必看)
  17. 游戏热更新(XLua)专题一(知识点)
  18. 万达VS银泰 谁是最后的赢家?
  19. 6.hadoop文件数据库系列讲解
  20. rockchip rk3368(px5)车载开发之路1,原生代码系统正常启动

热门文章

  1. 解决mac修改docker容器报错[screen is terminating]
  2. xadmin删除数据后出现ValueError报错
  3. JDK1.8版本,java并发框架支持锁包括
  4. Statefulset:部署有状态的多副本应用
  5. C#查找指定窗口的子窗口的句柄
  6. Nginx下Uwsgi模块常用参数说明
  7. 『设计模式』之小试牛刀
  8. JAVA中集合输出的四种方式
  9. 创新数字音频处理技术带来消费电子产品差异化用户体验(转)
  10. Linux内存之Cache