3.进程与线程

一、前言

线程与进程,这是两个非常通用的概念,并不仅仅局限于语言本身,因为这是操作系统所提供的,无论什么语言,特别是偏底层语言(比如c,c++,rust等),都能通过对应的接口来创建、操作进程与线程。

但同时要注意,操作系统也有不同类型的,比如主流的windows系统、linux系统、mac系统等等。

虽然各个系统都统一有进程与线程这两个概念,但具体的调用方式,也就是函数接口并不完全一致。

所以如果你使用C/C++在不同的系统上开发软件,并且不使用跨平台的库,那么调用的API就不相同,这也就导致你的程序不跨平台,从而开发难度倍增。

而高级的语言则会提供跨平台的库,比如java、python等等,无论什么平台,都给你提供统一的调用接口,从而实现一份代码,跨平台运行,减少程序员的开发量。

二、进程

首先我们来聊聊进程,最直观的解释就是:一个应用程序就是一个进程

或者更进一步的说,一个windows平台上以.exe后缀结尾的可执行文件,当其运行起来之后就是一个进程。

虽然这么说在现在看来有些不合适了,但对于新手理解起来确实会更加的容易。

并且我们可以在window系统中的任务管理器中看到当前电脑上所有运行中的进程(应用程序):

image-20230927143101328

如果不会调出任务管理器的,可以自己浏览器搜一搜,这个是很基础的内容。

这个页面就是当前我电脑上运行的所有进程,也就是所有的应用程序。

对于操作系统来说,进程是基本的资源分配单位。

怎么理解?比如上图每个进程后面有CPU、内存等内容,其中列出的就是当前某个进程所占用的系统内存、CPU,也就是系统资源。

所以如果你发现电脑卡了,就可以来到任务管理器中,看看是哪个进程占CPU、内存多,然后将它关闭即可。

这就是进程的基本概念:资源分配的基本单位

并且各个进程是彼此独立的,比如,你QQ崩溃了,一般来说,是不会影响微信的!

但你会发现,任务管理器中很多进程是可以展开的: image-20230927144021435

比如我在当前浏览器中,打开了本站点,这里就会出现一个标签页。

如果外面的Microsoft Edge是进程,那这些叫什么呢?它们后面也有内存、CPU占用啊!

而这就是前面我说的不合适的原因了,因为现在很多程序都偏爱制作多进程应用

也就是说,一个应用本身是一个进程组,它是一系列进程的集合,而不单单只是一个进程。

这样做肯定是有好处也有坏处的。

好处就是刚刚所说,进程之间相互彼此独立,比如浏览器中,我一个页面崩溃了,并不会导致整个浏览器崩溃,同时也不会影响到其它页面。

但坏处也很明显,因为每个进程都需要分配资源,就会导致多进程应用对资源占有量一般都比单进程要大的多。

不信的话你可以试一试在浏览器中一次性开几十个页面,一般电脑可能就直接卡死了。

以一个基本的C语言代码为例:

int main(){}

虽然它什么也没干,但只要你编译执行它,那它就是一个进程!

三、线程

进程很容易理解,就是电脑资源分配的基本单位嘛,并且各个进程相互独立。

那么线程呢?

可能你早就看到过线程的概念,只不过你从来没有注意过。

因为在你买手机、电脑的时候,一般都会有一个配置说明:几核几线程

比如我的电脑就是普通的4核8线程:

image-20230927145016193

一般来说,一个物理核心同时只能执行一个线程,只不过现代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(/*参数*/); //创建线程
}

这很繁琐,所以一般开发跨平台程序,都会使用高级语言、或者跨平台的第三方库。

作者:余识
全部文章:0
会员文章:0
总阅读量:0
c/c++pythonrustJavaScriptwindowslinux