进程线程

1 什么是进程,线程,彼此有什么区别⭐⭐⭐⭐⭐

程序只是一组指令的有序集合,它本身没有任何运行的含义,它只是一个静态的实体。而进程则不同,它是程序在某个数据集上的执行。进程是一个动态的实体,它有自己的生命周期。它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤消。反映了一个程序在一定的数据集上运行的全部动态过程。
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配的基本单位。进程是系统中正在运行的一个程序,程序一旦运行就是进程。
线程是进程的一个实体,作为系统调度和分配的基本单位,Linux下的线程看作轻量级进程。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

区别
1.一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程依赖于进程而存在。
2.进程在执行过程中拥有独立的内存单元,而多个线程共享进程的内存。(资源分配给进程,同一进程的所有线程共享该进程的所有资源。同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量。)
3.进程是资源分配的最小单位,线程是CPU调度的最小单位
4.系统开销:由于在创建或撤消进程时,系统都要为之分配或回收资源,如内存空间、I/O设备等。因此,操作系统所付出的开销将显著地大于在创建或撤消线程时的开销。类似地,在进行进程切换时,涉及到整个当前进程CPU环境的保存以及新被调度运行的进程的CPU环境的设置。而线程切换只须保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作。可见,进程切换的开销也远大于线程切换的开销。
5.通信:由于同一进程中的多个线程具有相同的地址空间,致使它们之间的同步和通信的实现,也变得比较容易。进程间通信IPC(管道,信号量,共享内存,消息队列) ,线程间可以直接读写进程数据段(如全局变量)来程通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。因为进程之间互不干扰,相互独立,进程的通信机制相对很复杂,譬如管道,信号,消息队列,共享内存,套接字等通信机制,而线程由于共享数据段所以通信机制很方便。
6.进程编程调试简单可靠性高,但是创建销毁开销大;线程正相反,开销小,切换速度快,但是编程调试相对复杂。
7.进程间
不会相互影响
;线程一个线程挂掉将导致整个进程挂掉
8.进程适应于多核、多机分布;线程适用于多核

2 多进程、多线程同步(通讯)的方法

转载

同步与互斥:简单的控制
通信:交互的信息更多
多线程的同步
1.锁机制:包括互斥锁、条件变量、读写锁
 互斥锁 pthread_mutex_t:此外还有自旋锁,读写锁等扩展,用于互斥,保证一个时刻只有一个线程执行
 条件变量pthread_cond_t:用于同步
2.信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
3.信号机制(Signal):类似进程间的信号处理
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。
多线程通信的方法主要有:
1.全局变量
进程中的线程间内存共享,这是比较常用的通信方式和交互方式。
2.Message消息机制
常用的Message通信的接口主要有两个:PostMessage和PostThreadMessage。PostMessage为线程向主窗口发送消息,而PostThreadMessage是任意两个线程之间的通信接口

多进程的同步
互斥锁 pthread_mutex_t:此外还有自旋锁,读写锁等扩展,用于互斥,保证一个时刻只有一个线程执行
条件变量pthread_cond_t:用于同步
信号量sem_t:用于控制资源的访问
多进程的通信
1.信号 ( sinal ) :信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。异步的通信机制
2.共享内存( sharedmemory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
3.管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
4.有名管道 (namedpipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
5.信号量( semophore ) :信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
6.消息队列( messagequeue ) :消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
7.套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

3 多进程、多线程的优缺点⭐⭐⭐⭐

线程执行开销小,但不利于资源的管理和保护;而进程正相反。
多进程优点:
1、每个进程互相独立,不影响主程序的稳定性,子进程崩溃没关系;
2、通过增加CPU,就可以容易扩充性能;
3、可以尽量减少线程加锁/解锁的影响,极大提高性能,就算是线程运行的模块算法效率低也没关系;
4、每个子进程都有2GB地址空间和相关资源,总体能够达到的性能上限非常大。
多进程缺点:
1、逻辑控制复杂,需要和主程序交互
2、需要跨进程边界,如果有大数据量传送,就不太好,适合小数据量传送、密集运算 多进程调度开销比较大;

多线程的优点:
1、无需跨进程边界
2、所有线程可以直接共享内存和变量等
3、线程方式消耗的总资源比进程方式少
多线程缺点:
1、每个线程与主程序共用地址空间,受限于2GB地址空间
2、线程之间的同步和加锁控制比较麻烦;
3、一个线程的崩溃可能影响到整个程序的稳定性;
4、线程能够提高的总性能有限,而且线程多了之后,线程本身的调度也是一个麻烦事儿,需要消耗较多的CPU。

3 用户线程和内核线程的区别

转载
1 .内核级线程:切换由内核控制,当线程进行切换的时候,由用户态转化为内核态。切换完毕要从内核态返回用户态;可以很好的利用smp,即利用多核CPU。
2. 用户级线程内核的切换由用户态程序自己控制内核切换,不需要内核干涉,少了进出内核态的消耗,但不能很好的利用多核cpu,目前Linux pthread大体是这么做的。

线程的实现可以分为两类:用户级线程(User-Level Thread)和内核线线程(Kernel-Level Thread),后者又称为内核支持的线程或轻量级进程。在多线程操作系统中,各个系统的实现方式并不相同,在有的系统中实现了用户级线程,有的系统中实现了内核级线程。
用户线程不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。不需要用户态/核心态切换,速度快,操作系统内核不知道多线程的存在,因此一个线程阻塞将使得整个进程(包括它的所有线程)阻塞。由于这里的处理器时间片分配是以进程为基本单位,所以每个线程执行的时间相对减少。
内核线程:由操作系统内核创建和撤销。内核维护进程及线程的上下文信息以及线程切换。一个内核线程由于I/O操作而阻塞,不会影响其它线程的运行。Windows NT和2000/XP支持内核线程。

用户级线程和内核级线程的区别:
(1)内核支持线程是OS内核可感知的,而用户级线程是OS内核不可感知的。
(2)用户级线程的创建、撤消和调度不需要OS内核的支持,是在语言(如Java)这一级处理的;而内核支持线程的创建、撤消和调度都需OS内核提供支持,而且与进程的创建、撤消和调度大体是相同的。
(3)用户级线程执行系统调用指令时将导致其所属进程被中断,而内核支持线程执行系统调用指令时,只导致该线程被中断。
(4)在只有用户级线程的系统内,CPU调度还是以进程为单位,处于运行状态的进程中的多个线程,由用户程序控制线程的轮换运行;在有内核支持线程的系统内,CPU调度则以线程为单位,由OS的线程调度程序负责线程的调度。
(5)用户级线程的程序实体是运行在用户态下的程序,而内核支持线程的程序实体则是可以运行在任何状态下的程序。

内核线程
优点:当有多个处理机时,一个进程的多个线程可以同时执行。
缺点:由内核进行调度。

用户线程的优点:
(1) 线程的调度不需要内核直接参与,控制简单。
(2) 可以在不支持线程的操作系统中实现。
(3) 创建和销毁线程、线程切换代价等线程管理的代价比内核线程少得多。
(4) 允许每个进程定制自己的调度算法,线程管理比较灵活。这就是必须自己写管理程序,与内核线程的区别
(5) 线程能够利用的表空间和堆栈空间比内核级线程多。
(6) 同一进程中只能同时有一个线程在运行,如果有一个线程使用了系统调用而阻塞,那么整个进程都会被挂起。另外,页面失效也会产生同样的问题。
缺点:资源调度按照进程进行,多个处理机下,同一个进程中的线程只能在同一个处理机下分时复用。

4 父进程、子进程的关系以及区别

子进程得到的除了代码段是与父进程共享以外,其他所有的都是得到父进程的一个副本,子进程的所有资源都继承父进程,得到父进程资源的副本,二者并不共享地址空间。两个是单独的进程,继承了以后二者就没有什么关联了,子进程单独运行。(采用写时复制技术)关于文件描述符:继承父进程的文件描述符时,相当于调用了dup函数,父子进程共享文件表项,即共同操作同一个文件,一个进程修改了文件,另一个进程也知道此文件被修改了。
fork出子进程后,子进程都会继承父进程以下信息;
1 已打开的文件描述符
2.实际用户ID,实际组ID,有效用户ID,有效组ID
3.进程组ID
4.添加组ID
5.对话期ID
6.控制终端
7.设置-用户-ID标志和设置-组-ID标志
8.当前工作目录
9.根目录
10.文件方式创建屏蔽字
11.信号屏蔽和排列
12.对任意打开文件描述符大的在执行时关闭标志。
13.环境
14.链接的共享存储段

父子进程间的区别
1.进程号PID
2.不同的父进程ID
3.fork的返回值
5.父进程设置的锁,子进程不继承
子进程不继承父进程的进程正文(text),数据和其他锁定内存(memory locks)
不继承异步输入和输出

5 什么时候用进程,什么时候用线程⭐⭐⭐

1.需要频繁创建销毁的优先使用线程;因为对进程来说创建和销毁一个进程的代价是很大的。
2.线程的切换速度快,所以在需要大量计算,切换频繁时使用线程,还有耗时的操作时用使用线程可提高应用程序的响应。
3.多进程可以使用在多机分布式系统,因为对CPU系统的效率使用上线程更占优势,多线程适用于多核处理机。
4.并行操作时用线程,如C/S架构的服务器端并发线程响应用户的请求。
5.需要更稳定安全时,适合选择进程;需要速度时,选择线程更好。

6 进程线程的状态转换图 什么时候阻塞,什么时候就绪

在这里插入图片描述
1 创建状态New
满足运行条件(分配到除CPU外的资源),进入就绪状态
2. 就绪状态Runnable/Start
获取CPU资源,得到时间片,进入运行状态
3. 运行状态Running
主动睡眠sleep(),进入Time Waiting状态
主动等待wait(),进入Waiting状态
I/O请求或者申请缓冲区失败,进入阻塞状态
中断或者执行完毕,进入终止阶段
时间片用完,进入就绪状态
4. Time Waiting
睡眠时间到,进入就绪状态
5. Waiting
被唤醒,进入就绪状态
6. 阻塞状态Blocked
I/O完成或者同步块释放,进入就绪状态
7. 消亡/终止状态Dead/Terminated
执行完了或者因异常退出了run()方法,该线程结束生命周期

阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

7 什么是进程上下文、中断上下文⭐⭐

任务上下文可包括程序计数器、堆栈指针、通用寄存器的内容
中断,异常,系统调用

内核态:在内核空间执行,通常是驱动程序,中断相关程序,内核调度程序,内存管理及其操作程序。
用户态:用户程序运行空间。
处理器是处于以下三种情况中的一种:
1、内核态,运行于进程上下文,内核代表进程运行于内核空间;
2、内核态,运行于中断上下文,内核代表硬件运行于内核空间;
3、用户态,运行于用户空间。
1.进程上下文:进程上下文就是一个进程在执行的时候,CPU的所有寄存器中的值、进程的状态以及堆栈上的内容。进程由用户态切换到内核态,它需要保存当前进程的所有状态,即保存当前进程的进程上下文,以便再次执行该进程时,能够恢复切换时的状态,继续执行。简单说当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。
2.中断上下文:硬件通过中断触发信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。中断上文可以看作就是硬件传递过来的这些参数和内核需要保存的一些其他环境(主要是当前被打断执行的进程环境)。

8 一个进程可以创建多少线程,和什么有关

理论上一个进程中可用的内存空间只有2G(32位4G,进程可分配2G),默认情况下,线程的栈的大小是1MB,所以理论上最多只能创建2048个线程,但是内存当然不可能完全拿来作线程的栈,所以实际数目要比这个值要小。
可以通过修改CreateThread函数参数来缩小线程栈StackSize。也可以通过连接时修改默认栈大小,这样就可以多开一些线程。物理内存再大,一个进程中可以起的线程总要受到2GB这个内存空间的限制。同一台机器内能起多少线程也是受内存限制的。每个线程对象都要占用非页面内存,而非页面内存也是有限的,当非页面内存被耗尽时,也就无法创建线程了。

©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页