进程和线程的区别
Posted 仇实
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了进程和线程的区别相关的知识,希望对你有一定的参考价值。
(1)
最大的区别
- 进程时系统资源分配的最小单位
- 线程时cpu操作和调度的最小单位,本质是一组寄存器的状态,是操作系统对寄存器状态的抽象
(2)
从创建和切换以及通信成本来说:
线程的创建成本远远低于进程
- 创建进程需要为进程划分出一块完整的内存空间,有大量的初始化操作,比如要把内存分段(堆栈、正文区等)。
- 创建线程则简单得多,只需要确定 PC 指针和寄存器的值,并且给线程分配一个栈用于执行程序,同一个进程的多个线程间可以复用堆栈。
- 因此,创建进程比创建线程慢,而且进程的内存开销更大。
进程上下文切换
当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够必得到切换时的状态执行下去。在LINUX中,当前进程上下文均保存在进程的任务数据结构中。在发生中断时,内核就在被中断进程的上下文中,在内核态下执行中断服务例程。但同时会保留所有需要用到的资源,以便中断服务结束时能恢复被中断进程的执行。
线程的上下文切换
线程和进程的区别,线程是调度的基本单位,进程时资源拥有的基本单位,怎么理解呢?所谓内核中的任务调度,实际上调度的对象是线程,而进程时给线程提供虚拟内存、全局变量等资源的。
你也可以这样理解:
当进程只有一个线程时,可以认为进程就等于线程;
当进程拥有多个线程时,这些线程共享相同的虚拟内存和全局变量等资源,这些资源在上下文切换时并不需要修改。
当线程也有自己的私有数据时,比如自己的栈和寄存器,上下文切换时也需要保存。
根据上面描述的,线程的上下文切换就存在两种情况:
- 前后切换的两个线程是属于同一个进程,两个线程的资源基本是共享的,切换上下文时共享的资源不需要动,只有当线程有私有数据时,切换这些不共享的数据即可;
- 前后切换的两个进程不属于同一个进程,跟切换进程的上下文时一样的。
切换同一进程的线程比切换进程消耗更少的系统资源,这就是多线程对比多进程的优势。
进程中的线程共享地址空间,进程间的通信的代价远大于线程间的通信
- 管道,FIFO,消息队列,信号量,共享内存,信号,socket,UNIX套接字
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。
- 互斥锁,读写锁,自旋锁,信号量,条件变量和屏障
(3)
在同一个进程中的线程有共享的和独有的资源
https://cloud.tencent.com/dev...
线程之间独有的资源有
栈区
- 同时函数运行时需要额外的寄存器来保存一些信息,像部分局部变量之类,这些寄存器也是线程私有的,一个线程不可能访问到另一个线程的这类寄存器信息。
- 所属线程的栈区、程序计数器、栈指针以及函数运行使用的寄存器是线程私有的。这些信息有一个统一的名字,就是线程上下文,thread context。
TLS -> Thread Local Storge
- 存放在该区域中的变量是全局变量,所有线程都可以访问他是全局的,但是每个线程在访问的时候都会存储一份成为自己的局部变量,修改就不会相互影响了
- 虽然看上去所有线程访问的都是同一个变量,但该全局变量独属于一个线程,一个线程对此变量的修改对其他线程不可见。
- 实现原理类似有一个全局的词典,词典的key是线程id,value就是共享的全局变量的副本。
http://blog.hacksmeta.com/201...
线程共享的资源
代码区
- 编译后的代码
数据区
- 全局变量,静态变量。
堆区
- C/C++中用malloc或者new出来的数据就存放在这个区域,只要知道指针,任何一个线程都可以访问指针指向的数据,因此堆区也是线程共享的属于进程的资源。
栈区
- 如果一个线程能拿到来自另一个线程栈帧上的指针,那么该线程就可以改变另一个线程的栈区,也就是说这些线程可以任意修改本属于另一个线程栈区中的变量。
动态链接库
- 动态链接的部分生成的库就是我们熟悉的动态链接库,在Windows下是以DLL结尾的文件,在Linux下是以so结尾的文件。
文件
- 如果程序在运行过程中打开了一些文件,那么进程地址空间中还保存有打开的文件信息,进程打开的文件也可以被所有的线程使用,这也属于线程间的共享资源。
以上是关于进程和线程的区别的主要内容,如果未能解决你的问题,请参考以下文章