一、前言
线程与进程,这是两个非常通用的概念,并不仅仅局限于语言本身,因为这是操作系统所提供的,无论什么语言,特别是偏底层语言(比如c,c++,rust等),都能通过对应的接口来创建、操作进程与线程。
但同时要注意,操作系统也有不同类型的,比如主流的windows系统、linux系统、mac系统等等。
虽然各个系统都统一有进程与线程这两个概念,但具体的调用方式,也就是函数接口并不完全一致。
所以如果你使用C/C++在不同的系统上开发软件,并且不使用跨平台的库,那么调用的API就不相同,这也就导致你的程序不跨平台,从而开发难度倍增。
而高级的语言则会提供跨平台的库,比如java、python等等,无论什么平台,都给你提供统一的调用接口,从而实现一份代码,跨平台运行,减少程序员的开发量。
二、进程
首先我们来聊聊进程,最直观的解释就是:一个应用程序就是一个进程
或者更进一步的说,一个windows平台上以.exe
后缀结尾的可执行文件,当其运行起来之后就是一个进程。
虽然这么说在现在看来有些不合适了,但对于新手理解起来确实会更加的容易。
并且我们可以在window系统中的任务管理器中看到当前电脑上所有运行中的进程(应用程序):
如果不会调出任务管理器的,可以自己浏览器搜一搜,这个是很基础的内容。
这个页面就是当前我电脑上运行的所有进程,也就是所有的应用程序。
对于操作系统来说,进程是基本的资源分配单位。
怎么理解?比如上图每个进程后面有CPU、内存等内容,其中列出的就是当前某个进程所占用的系统内存、CPU,也就是系统资源。
所以如果你发现电脑卡了,就可以来到任务管理器中,看看是哪个进程占CPU、内存多,然后将它关闭即可。
这就是进程的基本概念:资源分配的基本单位。
并且各个进程是彼此独立的,比如,你QQ崩溃了,一般来说,是不会影响微信的!
但你会发现,任务管理器中很多进程是可以展开的:
比如我在当前浏览器中,打开了本站点,这里就会出现一个标签页。
如果外面的Microsoft Edge
是进程,那这些叫什么呢?它们后面也有内存、CPU占用啊!
而这就是前面我说的不合适的原因了,因为现在很多程序都偏爱制作多进程应用。
也就是说,一个应用本身是一个进程组,它是一系列进程的集合,而不单单只是一个进程。
这样做肯定是有好处也有坏处的。
好处就是刚刚所说,进程之间相互彼此独立,比如浏览器中,我一个页面崩溃了,并不会导致整个浏览器崩溃,同时也不会影响到其它页面。
但坏处也很明显,因为每个进程都需要分配资源,就会导致多进程应用对资源占有量一般都比单进程要大的多。
不信的话你可以试一试在浏览器中一次性开几十个页面,一般电脑可能就直接卡死了。
以一个基本的C语言代码为例:
int main(){}
虽然它什么也没干,但只要你编译执行它,那它就是一个进程!
三、线程
进程很容易理解,就是电脑资源分配的基本单位嘛,并且各个进程相互独立。
那么线程呢?
可能你早就看到过线程的概念,只不过你从来没有注意过。
因为在你买手机、电脑的时候,一般都会有一个配置说明:几核几线程。
比如我的电脑就是普通的4核8线程:
一般来说,一个物理核心同时只能执行一个线程,只不过现代CPU大多采用了超线程技术,让一个物理核心可以同时执行两个线程,因此线程数量就是核心数量的两倍。
而CPU核心是干嘛的?当然是执行计算的呀!换句话说,就是执行代码的!
所以你大概也就能想到线程是什么东西了,它就是CPU执行的基本单位!
也就是说,上面谈到的进程,仅仅只是从电脑分配到了基本的资源,但内部的代码得靠CPU执行才行。
而CPU不能执行进程,只能执行线程。
所以你也就能搞清楚两者的关系了:进程包含线程。
那我怎么看不到线程呢?
这个确实,线程不容易被看到,但只要你写过代码,就一定用到过。
还是一个最简单的c语言例子:
int main(){}
进程不执行代码,执行代码的是线程,所以只要你编译上面的代码并执行后,就有一个你看不到的线程,会执行main
函数。
这个线程是伴随进程产生的,一般被称为主线程,从main
函数开始,从开始执行到结束。
如果主线程结束了,那么这个进程也就会被自动终止了。
而所谓的多线程,就是由主线程在这个进程的内部再创建几个子线程一起来干活。
比如我的电脑CPU为4核8线程,也就是同时最多能有8个线程一起工作,相比于你只使用一个主线程而言,可以极大提高效率。
线程的优点很明显,就是它依赖进程而生,所以需要的资源量较少。
但缺点也同样的,因为它依赖于进程,所以如果一个进程里的多线程,任何一个线程崩溃了,都会直接影响整个程序。
如果浏览器采用多线程技术开发的话,就意味着,只要你某个页面崩溃了,整个浏览器也会直接崩溃。
另一个要点就是,多线程依赖于一个进程,所以多线程之间是可以很方便的共享资源的。
比如在C/C++中,直接定义一个全局变量,所有线程都可以访问,但这样容易出问题,不过这就是多线程编程要解决的问题了。
多进程当然也是可以共享资源的,只不过用到的技术会复杂的多,依靠的是几种比较复杂的进程间通信方式来实现的。
这个如果以后有机会再提。
四、总结
最后再来稍微总结一下两者的区别。
首先是进程,它是系统分配资源的基本单位,多个进程互相独立,占用资源量较大,本身并不执行代码,一个进程中最少都有一个线程用于执行代码。
然后是线程,它是系统执行程序的基本单位,并且依赖于进程存在,占用资源量较少,同一进程中的多线程可以非常容易的共享资源,任何一个线程崩溃都会导致当前进程的崩溃。
两者并不存在谁好谁坏的说法,在适当的时候使用适当的技术即可。
至于如何使用,这取决于你使用的语言,比如C/C++在windows系统平台创建线程与进程使用的函数:
#include<windows>
int main(){
CreateProcress(/*很多参数*/);//创建进程
CreateThread(/*很多参数*/); //创建线程
}
而在linux平台就是:
#include <sys/types.h>
#include <unistd.h>
int main(){
fork();// 创建进程
pthread_create(/*参数*/); //创建线程
}
这很繁琐,所以一般开发跨平台程序,都会使用高级语言、或者跨平台的第三方库。