1、线程与进程的区别

(1)线程是轻量级的进程,是程序执行流的最小单位;
(2)进程是资源分配的最小单位,线程是调度的最小单位;
(3)进程可以创建线程,线程不可以创建进程;
(4)一个进程由一个或者多个线程组成;
(5同进程的线程间可以自由通信;
(6)不同的进程间通信,必须用进程间的通信方法(比如:共享内存、管道等),效率比线程间通信低且麻烦;

2、线程的定义

(1)线程的组成:线程ID、当前指令指针(PC)、寄存器集合、堆栈;
(2)一个进程包含一个或者多个线程,其中进程的大部分资源(代码段、数据段、堆段、打开文件/信号等)都是线程间共享的,线程会保留一部分私有数据(寄存器、栈);

3、线程的访问权限

虽然同进程内的线程之间数据访问很自由,但是每个线程也拥有自己的私有存储空间,包括以下方面:
(1)栈空间;
(2)线程局部存储(Thread Local Storage, TLS):某些操作系统为线程单独提供的私有空间,通常只具有很有限的容量;
(3)寄存器(包括PC寄存器):寄存器是执行流的基本数据,因此为线程私有;

4、使用多线程的好处

(1)某个操作可能会陷入长时间等待,如果是单线程则进入睡眠,无法进行执行;如果是多线程,则可以让执行这个操作的线程睡眠,让CPU去执行其他任务的线程;
(2)某个操作会消耗大量的时间,如果只有一个线程,则线程会一直执行这个操作,导致程序和用户之间的交互中断;如果是多线程,则可以一个线程负责计算,另一个线程负责交互,两个线程交替在CPU上执行;
(3)现在的CPU基本都是多核的,本身就具备同时执行多个线程的能力,因此单线程是无法全面发挥计算机的性能;
(4)想较与多进程应用,多线程在数据共享方面的效率要高很多,编写代码也更方便;
补充:在嵌入式开发中,能用多线程解决就不用多进程;

5、线程的调度

5.1、线程的状态

状态 含义
运行态 线程正在CPU上运行
就绪态 线程已经具有除CPU之外的所有资源,等待分配到CPU就可以运行
阻塞态 线程等待某一个事件的发生或者等待得到某样资源(除CPU资源外),无法被执行

(1)上图展示的是线程最基本的三种状态(运行态、就绪态、等待态也叫阻塞态),实际的线程状态比这个要复杂(比如还有挂起态),这里不展开讲;
(2)运行态->就绪态:线程在CPU上运行,运行至时间片耗尽会被剥夺CPU的使用权,CPU会去执行其他的线程,而该线程进入就绪态,等待被CPU再次调度;
(3)运行态->阻塞态:线程在CPU上运行,在时间片耗尽之前因为缺少某样资源而无法继续执行从而阻塞,线程会变为阻塞态,CPU会去调用其他的线程;
(4)阻塞态->就绪态:导致线程阻塞的事件发生,线程具有了除CPU意外的所有资源,线程变为就绪态,等待被CPU调度;
(5)就绪态->运行态:线程具有了除CPU意外的所有资源,被CPU调度从而在CPU上运行,此时线程变为了运行态;
总结:线程在几种状态间的转换就叫做线程调度;

5.2、线程优先级

(1)在linux中线程分为0~99的100个优先级,数值越大优先级越高,linux中有专门的API设置线程的优先级;
(2)给线程设置优先级是为了提高响应速度,改善用户的使用体验;
(3)一般来说,跟用户交互的线程优先级要设置的高一些,后台运行的线程优先级设置的低一些;比如:你肯定不希望点一下鼠标要几秒才有反应,所以检测鼠标事件的线程优先级要设置的高一些;
(4)优先级高的线程会优先被CPU调度,但是需要注意不能产生饿死现象,理想的情况:高优先级的线程会先运行,低优先级的线程稍后运行,但不能让低优先级的线程被饿死;

5.3、线程的调度策略

(1)SCHED_OTHER:分时调度策略;
(2)SCHED_FIFO:实时调度策略,先到先服务。一旦占用cpu则一直运行,一直运行直到有更高优先级任务到达或自己放弃;
(3)SCHED_RR:实时调度策略,时间片轮转。当进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾。放在队列尾保证了所有具有相同优先级的RR任务的调度公平;

5.4、线程调度算法

(1)先来先服务:操作系统维护一个等待队列,需要CPU的线程就加入等待队列进行排队,操作系统按照先后顺序去调度线程。算法实现很简单,但是没有考虑线程执行的任务之间存在轻重缓急;
(2)最短作业优先:选择执行时间最短的作业最先执行;
(3)最短剩余时间优先:调度程序总是选择其剩余运行时间最短的那个进程运行,
(4)最高响应比优先算法:为每个线程计算出响应比,响应比高的优先被运行,为了解决饿死的线程,线程的响应比是动态变化的,总体趋势: 每个作业随着在后备池等待时间的增长其响应比也不断增长,而且,预计运行时间越短的作业响应比增长越快;
(5)轮转法:将CPU的运行划分成时间片,每个线程在CPU上运行直到时间片耗尽,时间片耗尽后就调度其他就绪态的线程在CPU上运行;
(6)最高优先级算法:调度每次将CPU分配给具有最高优先级的就绪线程;
(7)多级反馈队列算法:结合了前面的好几种算法,比前面介绍的调度算法都更优秀,比较复杂,这里不详细介绍;

5.5、可抢占线程和不可抢占线程

(1)抢占:线程在用尽时间片后被强制剥夺CPU的使用权,进入就绪态;
(2)不可抢占线程:除非线程主动放弃CPU使用权或者进入阻塞态时,CPU才会被让渡给其他线程,否则其他线程将无法运行;
(3)可抢占线程:时间片耗尽就让渡出CPU;
补充:现在基本都是可抢占的线程;

6、线程安全

6.1、引起线程安全问题的原因

(1)多个线程对共享资源进行操作时,由于线程之间感知不到其他线程对共享资源的操作,所以可能出现线程对共享资源的访问冲突;
(2)比如:很经典的例子,两个线程对同一个int型变量i各进行"++"操作一百次,最后发现i的值不是200;

6.2、线程同步的方法

(1)二元信号量:特殊情况的信号量,信号量的值是1,只有两种状态(占用与非占用),被锁住的资源同时只允许一个线程操作;
(2)多元信号量:信号量的值大于1,允许多个线程访问共享资源,通过P操作和V操作来进行线程间同步;
(3)互斥量:和二元信号量类似,资源仅同时运行一个线程访问,不同之处在于信号量可以被任意线程获取或释放,而互斥量只能谁获取谁释放;
(4)临界区:比互斥量更严格,只有创建临界区的进程才能获得锁,其他进程无法获取该锁。把获取临界区的锁称为进入临界区,把释放临界区的锁称为离开临界区;
(5)读写锁:适合频繁读取偶尔写入的情况,允许读状态时共享,写状态时独占;
(5)条件变量:线程可以等待某个条件变量,当条件变量不满足条件时,线程进入睡眠;线程也可以去唤醒条件变量,当条件变量满足条件时,等到条件变量的线程都会被唤醒;

6.3、可重入函数与不可重入函数

6.3.1、两者的区别

(1)函数重入:函数没有执行完成,由于外部因素或内部调用,又一次进入该函数执行;
(2)区别:可重入函数被多个线程同时调用不会出错,不可重入函数只允许同时被一个线程调用;
(3)可重入函数是线程并发执行的安全保障,在进行多线程编程时需要注意线程是否可重入;

6.3.2、可重入函数要满足的条件

(1)不使用任何(局部)静态或全局的非const变量;
(2)不返回任何(局部)静态或全局的非const变量的指针;
(3)仅依赖于调用方传入的参数;
(4)不依赖任何单个资源的锁;
(5)不调用任何不可重入的函数;

7、三种算法模型

内核线程和用户态线程

(1)我们调用内核的API创建的是用户态线程,不是内核态线程;
(2)内核线程负责管理和调度用户态的线程;
(3)用户态线程并不一定在操作系统里对应相等数量的内核线程;

7.1、一对一模型

优点:
(1)一个用户态线程对应一个内核态线程,使得用户态的线程具有了和内核线程一致的优点,用户线程直接实现真正的并发;
(2)一个用户态线程因为某些原因阻塞时,其他用户态线程执行不会收到影响;
缺点:
(1)操作系统限制了内核线程的数量,因此一对一模型会让用户的线程数量受到限制;
(2)操作系统的内核线程调度,上下文切换的开销较大,导致用户线程的执行效率下降;

7.2、多对一模型

优点:
(1)将多个用户态线程映射到一个内核线程上,用户态线程之间切换开销小,执行效率高;
(2)多对一模型使得用户态线程可以无限制的增加;
缺点:
(1)当一个用户态线程阻塞时,映射到同一个内核线程的用户态线程全部阻塞;

7.3、多对多模型

多对多模型结合了多对一和一对一模型的特点,克服了缺点保留了优点,将多个用户态线程映射到少数但不止一个内核线程上;
优点:
(1)一个用户态线程阻塞不会使得所有用户态线程阻塞,因为还有别的内核线程可以调度;
(2)多对多模型对用户态线程的数量也没有限制,在多处理器系统上,多对多模型的线程也能得到一定的性能提升,不过提升的幅度不如一对一模型高;

linux线程详解:线程概念、线程调度、线程安全、线程模型相关推荐

  1. android任务 进程 线程详解,Android任务、进程、线程详解

    singleTop模式,基本上于standard分歧,仅正在请求的Activity反好位于栈顶时,无所区别.此时,配放成singleTop的Activity,不再会构制新的实例加入到Task栈外,而是 ...

  2. Java线程详解(1)-概念与原理

    一.进程与线程 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,即进程空间或(虚空间).进程不依赖于线程而独立存在,一个进程中可以启动多个线程.比如在Windows系统中,一个运 ...

  3. Java线程详解(12)-有返回值的线程

    在Java5之前,线程是没有返回值的,常常为了"有"返回值,破费周折,而且代码很不好写.或者干脆绕过这道坎,走别的路了.现在Java终于有可返回值的任务(也可以叫做线程)了. 可返 ...

  4. 『Linux』第九讲:Linux多线程详解(三)_ 线程互斥 | 线程同步

    「前言」文章是关于Linux多线程方面的知识,上一篇是 Linux多线程详解(二),今天这篇是 Linux多线程详解(三),内容大致是线程互斥与线程同步,讲解下面开始! 「归属专栏」Linux系统编程 ...

  5. 通用线程:POSIX 线程详解,第 2部分——称作互斥对象的小玩意

    通用线程:POSIX 线程详解,第 2部分--称作互斥对象的小玩意 Daniel Robbins (drobbins@gentoo.org), 总裁/CEO, Gentoo Technologies, ...

  6. Python线程详解

    Python线程详解 线程简介 开启多线程 线程之间共享 GIL全局解释器锁 线程间通信 线程简介 线程,有时被称为轻量进程(Lightweight Process,LWP),是程序执行流的最小单元. ...

  7. python与golang_Golang与python线程详解及简单实例

    Golang与python线程详解及简单实例 在GO中,开启15个线程,每个线程把全局变量遍历增加100000次,因此预测结果是 15*100000=1500000. var sum int var ...

  8. VC-终止线程,ExitThread函数,Te r m i n a t e T h r e a d函数,撤消线程,详解

    VC-终止线程,ExitThread函数,Te r m i n a t e T h r e a d函数,撤消线程,详解 6.5 终止线程的运行 若要终止线程的运行,可以使用下面的方法: •  线程函数 ...

  9. Linux Socket详解 大全 基础知识

    1. Socket基础概念: 1.1:形象类比: Socket和电话网络的概念可以做一个很好的类比: Linux 编程中所说的socket就如同一个端点,类比到电话网中,它就如同一个电话机. 而Soc ...

  10. Linux进程详解 【Linux由基础到进阶】

    Linux进程详解 进程的概念: 虚拟处理器: 虚拟内存: 进程的产生 进程的管理 进程描述符 分配进程描述符 进程描述符的存放 进程的状态 设置进程状态 进程上下文 系统调用与库函数的区别 进程家族 ...

最新文章

  1. php样式无法加载 路径对的,网站首页 有时加载不了样式
  2. Android线程池的简单使用
  3. Java虚拟机(五)——程序计数器
  4. OpenCV精进之路(二十二):实例——皮肤检测技术
  5. matlab2c使用c++实现matlab函数系列教程-exprnd函数
  6. java初级面试总结
  7. 海信电视开启开发者模式
  8. 服务器raid卡维修,服务器Raid卡故障|服务器RAID卡坏恢复数据
  9. 打印水果价格表(python)
  10. 基于Autoware制作高精地图(二)
  11. jupyter notebook修改字体
  12. Windows Server 2016 ServU-v6.30
  13. 清除Windows系统用户密码
  14. python智能写小说软件_Scratch编程实现智能自动创作写小说,自动生成文章,自动写材料...
  15. 九零后看什么网络电视
  16. 证明:gcd(m,n)=gcd(n mod m,m)成立,m,n为正整数,m>0. 【Euclid算法证明】
  17. Kubernetes系统日志查看命令
  18. ヾ(⌐ ■_■)— CSS简介篇
  19. 区块链学习笔记之三术语速查
  20. 软件工程--理论与实践 微课视频第二版 吕云翔 答案(应用 选择 判断)

热门文章

  1. 宏病毒组(四)|病毒注释软件介绍
  2. osg自定义操作器实现视图缩放
  3. select设置选中option
  4. xshell6 添加快速命令
  5. java教务管理系统数据库设计_计算机毕业设计选题及代做定做流程
  6. tinyint 范围
  7. Android开发最佳实践
  8. 大批量快速插入数据方法
  9. C语言开发情人节玫瑰
  10. NumPy库回顾与分享(一)