一、线程,进程,协程的区别? html
- 进程是 具备独立功能的程序的一次运行活动,是 系统进行资源分配和调度的一个独立单位。
- 线程是 进程的一个执行单元,是CPU执行的基本单位
- 一个进程能够有多个线程,多个线程也能够并发执行(单线程CPU 在同一时间内只可以运行一个线程,多核 CPU 能够同时调度多个线程执行)
- 1)进程间相互独立,同一进程的各线程间共享进程中的资源。某进程内的线程在其它进程不可见
2)调度和切换:线程上下文切换比进程上下文切换要快得多
3)线程不可以独立执行,必须依存在进程中,由应用程序提供多个线程执行控制
- 能够建立线程来异步处理一些计算,像Unity的Job System就可让粒子、动画、资源加载、场景加载等等放到Worker Threads中,利用多核特性对性能进行优化。
- 另外Unity还提供了协程来模拟多线程,将一个函数分红多个部分来顺序执行,本质是一个迭代器块,仍是在主线程执行,用yield return返回
- GPU并行计算
线程执行开销小,但不利于资源的管理和保护;而进程正相反。
二、哪些资源是进程共享的?
多个进程 能够共享 进程代码段data section、进程的公有数据(线程间通信)等系统资源,能够调用同一段程序代码
三、进程中的哪些资源是线程共享的?
线程私有
程序计数器 :每一个线程都有本身独立的程序计数器,用来指示下一条指令的地址。
虚拟机栈:即栈区,在编译期间完成分配。
线程共享
堆:垃圾收集器管理的主要区域。
方法区 :全部线程共享,存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。这个区域的内存回收目标主要是针对常量池的对象的回收和对类型的卸载。
线程共享资源
|
线程独享资源
|
地址空间 data section
|
程序计数器
|
全局变量 global
|
寄存器
|
打开的文件 file fd
|
栈
|
子进程
|
状态字
|
闹铃
|
|
|
|
记帐信息 id
|
|
四、进程通讯方式
- 进程互斥与同步(PV)
- 信号signal 与 信号量semaphore
- 共享存储器系统(共享存储区)
- 消息传递系统(直接发送/信箱通讯)
- 管道通讯系统(共享文件)
- socket、文件锁
全局变量则不是
管道是半双工的,
是一种固定大小的缓冲区。当管道满时,进程在写管道会被阻塞,而当管道空时,进程读管道会被阻塞
五、进程同步
在多道程序环境下,进程是并发执行的,不一样进程之间存在着不一样的相互制约关系(互斥和同步)。进程同步是对多个进程的执行顺序进行协调
互斥:
争用资源,指某一资源同时只容许一个访问者对其进行访问(没法限制顺序),经常使用 互斥信号量 记录PV
互斥量 mutex
,至关于一把锁,保证同类进程互斥
C#中的lock是互斥量,但用于线程间互斥
同步:一个进程在某一点等待另外一个进程提供信息,两进程存在直接的制约关系 。同步实现访问者对资源的有序访问。在大多数状况下,同步已经实现了互斥。少数状况是指能够容许多个访问者同时访问资源。
临界资源 :一次仅容许一个进程使用的资源。
临界区 :每一个进程中访问临界资源的那段程序代码
信号量S(用于同步)
当它的值小于
0时,其绝对值表示等待使用该资源的进程个数。
信号量机制-PV操做
--wait ++signal 操做
信号量用于 进程间或线程间,生产者消费者问题等……
进程同步有哪几种机制
- 原子操做:指不会被线程调度机制打断的操做。这种操做一旦开始,就一直运行到结束,中间不会有任何context switch(切换到另外一个线程)
- 信号量机制:PV操做。必须有公共内存,不能用于分布式操做系统,这是它最大的弱点。
- 自旋锁: 调用者申请的资源若是被占用,即自旋锁被已经被别的执行单元保持,则调用者一直循环在那里看是否该自旋锁的保持着已经释放了锁(比较低级)
- 管程: 将共享变量和对它们的操做集中在一个模块中,操做系统或并发程序就由这样的模块构成。模块之间联系清晰,便于维护和修改,易于保证正确性
- 会合:进程间直接进行相互做用, 一个进程能够调用另外一个进程的入口。先到达会合处的等待后到达者 +FCFS。分布式系统可用。
- 分布式系统: 网络上的一组计算机造成的系统。参数全为值参, 并且不可为指针。
原子操做是不可分割的。在单处理器系统(UniProcessor)中,可以在单条指令中完成的操做均可以认为是" 原子操做",由于中断只能发生于指令之间
可是,在对称多处理器(Symmetric Multi-Processor)中,因为系统中有多个处理器在独立地运行,即便能在单条指令中完成的操做也有可能受到干扰。咱们以decl (递减指令)为例,这是一个典型的"读-改-写"过程,涉及两次内存访问,CPU A、B各自存到本身的寄存器处理,最后写入内存的结果可能就不正确(多核CPU通常一级缓存与二级缓存是每一个核心进行分别均衡分配的,三级缓存才是多个核心一块儿共享的 )
C++有atomic_flag,atomic<T>,atomic……略。除此以外的操做不保证是原子操做
对于指针强制类型转换或者c++ placement new等状况,可能没法保证struct或class里的成员不跨越cacheline
六、线程同步的方式有哪些?
- 临界区(Critical Section): 在任意时刻只容许一个线程对共享资源进行访问,经过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。不能跨进程,只能实现线程互斥
- 互斥量:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。由于互斥对象只有一个,因此能够保证公共资源不会被多个线程同时访问。
- 信号量:它容许同一时刻多个线程访问同一资源,可是须要控制同一时刻访问此资源的最大线程数量。
- 事件(信号):经过通知操做的方式来保持多线程同步,还能够方便的实现多线程优先级的比较操做。
以上Event、Semaphore、Mutex 是内核对象,可以跨进程使用
七、什么是死锁
在两个或者多个并发进程中,若是每一个进程
持有某种资源而又等待其它进程释放它或它们如今保持着的资源,在未改变这种状态以前都不能向前推动,称这一组进程产生了死锁。
死锁产生的缘由
系统资源不足,进程推动顺序不当
死锁的4个必要条件 怎么处理
- 互斥条件:资源互斥 一个资源一次只能被一个进程使用
- 请求与保持条件:占有并等待 一个进程因请求资源而阻塞时,对已得到资源保持不放
- 不剥夺条件: 不可抢占 进程得到的资源,在未彻底使用完以前,不能强行剥夺
- 循环等待条件:循环等待 若干进程之间造成一种头尾相接的环形等待资源关系
处理死锁的策略
1)预防死锁: 破坏四个条件 资源静态分配
2)避免死锁: 如银行家算法,而是在资源的动态分配过程当中,用某种方法去防止系统进入不安全状态,从而避免发生死锁。
3)检测和解除死锁:死锁检测算法
4)不处理:鸵鸟算法,用于当死锁真正发生且影响系统正常运行时,才手动干预,从新启动
安全状态指存在安全序列。系统在进行资源分配以前,先计算资源分配的安全性,若这次分配会致使系统进入不安全状态,则进程等待。
存在安全序列时,就可避免死锁发生
系统进入不安全状态(四个死锁的必要条件同时发生)未必就会产生死锁。固然,产生死锁后,系统必定处于不安全状态。
八、虚拟内存
32位机中,每一个进程最大2^32地址(由于指针4字节寻址),即4GB虚拟内存
将那些当前要运行的少数页面或段先装入内存即可运行,其他部分暂留在盘上。
当内存耗尽时,电脑会自动调用硬盘来充当内存,以缓解内存的紧张。 若计算机运行程序或操做所需的随机存储器(RAM)不足时,则Windows 会用虚拟存储器进行补偿。 它将计算机的RAM和硬盘上的临时空间组合。 当RAM运行速率缓慢时,它便将数据从RAM移动到称为“分页文件”的空间中。
虚拟存储器是由硬件和操做系统自动实现存储信息调度和管理的。它的工做过程包括6个步骤:
①中央处理器访问主存的逻辑地址分解成组号a和组内地址b,并对组号a进行地址变换,即将逻辑组号a做为索引,查地址变换表,以肯定该组信息是否存放在主存内。
②如该组号已在主存内,则转而执行④;若是该组号不在主存内,则检查主存中是否有空闲区,若是没有,便将某个暂时不用的组调出送往辅存,以便将这组信息调入主存。
③从辅存读出所要的组,并送到主存空闲区,而后将那个空闲的物理组号a和逻辑组号a登陆在地址变换表中。
④从地址变换表读出与逻辑组号a对应的物理组号a。
⑤从物理组号a和组内字节地址b获得物理地址。
⑥根据物理地址从主存中存取必要的信息。
若是程序要访问的页/段还没有调入,那么请求调入
若是内存已满,则利用置换功能调出到盘上