进程、线程概念有意思的探讨

进程、线程概念有意思的探讨

1. 历史进程概念说起

从一个历史的概念说起,比如 1840-1919年近代化历史进程分为如下三个阶段:

(一)鸦片战争——甲午战争:主要学习西方科学技术,尤其是军事技术

(二)甲午战后——辛亥革命:主要学习西方政治制度。

(三)新文化运动——五四运动:主要学习西方思想文化并最终选择了马克思主义。

城市换进程
城镇化进程中的生态文明建设所要解决的矛盾

历史进程解决的矛盾:

2. 计算机的进程

2.1 对计算机来说

  • 进程是一个运行程序。进程是一个操作系统级别的概念,用来描述一组资源(比如外部代码库和主线程)和程序运行必须的内存分配。对于每一个加载到内存的*.exe,在它的生命周期中操作系统会为之创建一个单独且隔离的进程。

  • 由于一个进程的失败不会影响其他进程,使用这种隔离方式,运行环境将更加健壮和稳定。此外,一个进程无法访问另外一个进程中的数据,除非 使用WCF这种分布式计算编程的API。所以,进程是一个正在运行的应用程序的固定的安全的边界。

  • 每一个Windows进程都有一个唯一的进程标识符,即PID,当需要时,它们能被操作系统加载和卸载。

2.1 计算机处理资源需要利用进程解决的矛盾:
在这里插入图片描述
在这里插入图片描述

3. 计算机的线程

线程是进程中的基本执行单元。

  • 每一个Windows进程都包含一个用作程序入口点的主线程。进程的入口点创建的第一个线程被称为主线程。.Net控制台程序使用Main()方法作为程序入口点。当调用该方法时,会自动创建主线程。
  • 仅包含一个主线程的进程是线程安全的,这是由于在某个特定时刻只有一个线程访问程序中的数据。然而,如果这个线程正在执行一个复杂的操作,那么这个线程所在的进程(特别是GUI程序)对用户来说会显得没有响应一样。
  • 因此,主线程可以产生次线程(也称为工作者线程,worker thread)。每一个线程(无论主线程还是次线程)都是进程中的一个独立执行单元,它们能够同时访问那些共享数据。
  • 开发者可以使用多线程改善程序的总体响应性,让人感觉大量的活动几乎在同一时间发送。比如,一个应用程序可以产生一个工作者线程来执行强度大的工作。当这个次线程正在忙碌的时候,主线程仍然对用户的输入保持响应,这使得整个进程具有更强的性能。当然,如果单个进程中的线程过多的话,性能反而会下降,因为CPU需要花费不少时间在这些活动的线程来回切换。
  • 单CPU的计算机并没有能力在同一时间运行多个线程。准确地说,在一个单位时间(即一个时间片)内,单CPU只能根据线程优先级执行一个线程。当一个线程的时间片用完的时候,它会被挂起,以便执行其他线程。对于线程来说,它们需要在挂起前记住发生了什么,它们把这些情况写到线程本地存储中(Thread Local Storage,TLS),并且它们还要获得一个独立的调用栈(call stack)。
    在这里插入图片描述

我是你的博客(包括你的英文BLOG)的忠实读者。这个回复纯属技术探讨。

你这篇关于进程和线程的文章,图文并茂,很通俗,但不易懂。坦白说,在我看来很多比喻很不恰当,比如:

  1. 车间/电力/人三者,来比喻进程/CPU/线程三者,其实既没有体现出进程作为程序的一次执行(有独立的内存空间)这一特点,也没有体现出线程作为CPU调度单位这一特点。人和电力的关系是什么呢?所以“车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的”,这句话就很难理解。
  2. 用厕所容量,来比喻锁,也不合适。因为线程间同步是为了防止竞争(就是说因同时修改,而导致的数据不一致)。本质上讲,进程的内存空间是天然独立的,线程的内存空间是天然共享的。正因为如此,进程通信/线程同步才是系统编程的很大一块内容。

进程和线程简单而基本靠谱的定义如下:

  1. 进程:程序的一次执行
  2. 线程:CPU的基本调度单位
    这两个概念虽然过于简单,但是完全可以为理解OS/线程/进程打下坚实的基础,我认为关于进程/线程的探讨,无论采用何种方式,都必须以这两句话为落脚点,才算靠谱。

你写的大多数文章相当出色。在以通俗的方式解释复杂的概念这方面,尤其出色。但是,我个人的经验,这种方式比较适合用来解释一个复杂概念的一个方面,或者从某个角度的理解。想面面俱到的说明白一个复杂的系统,繁琐枯燥的概念,以及这些概念间的推演几乎不可避免。坦白说,在实际项目中大量用到线程/进程之前,我看过很多遍相关的概念,也写过小的示例程序,但真到了用的时候,还是发现之前没搞明白。

我对进程/线程的理解也很粗浅。个人见解,仅供参考。

抛开各种技术细节,从应用程序角度讲:

- 1、在单核计算机里,有一个资源是无法被多个程序并行使用的:cpu。

  • 没有操作系统的情况下,一个程序一直独占着全都cpu。
  • 如果要有两个任务来共享同一个CPU,程序员就需要仔细地为程序安排好运行计划–某时刻cpu和由程序A来独享,下一时刻cpu由程序B来独享
  • 而这种安排计划后来成为OS的核心组件,被单独名命为“scheduler”,即“调度器”,它关心的只是怎样把单个cpu的运行拆分成一段一段的“运行片”,轮流分给不同的程序去使用,而在宏观上,因为分配切换的速度极快,就制造出多程序并行在一个cpu上的假象。

2、在单核计算机里,有一个资源可以被多个程序共用,然而会引出麻烦:内存。

在一个只有调度器,没有内存管理组件的操作系统上,程序员需要手工为每个程序安排运行的空间 – 程序A使用物理地址0x00-0xff,程序B使用物理地址0x100-0x1ff,等等。

然而这样做有个很大的问题:每个程序都要协调商量好怎样使用同一个内存上的不同空间,软件系统和硬件系统千差万别,使这种定制的方案没有可行性。
为了解决这个麻烦,计算机系统引入了“虚拟地址”的概念,从三方面入手来做:

2.1、硬件上,CPU增加了一个专门的模块叫MMU,负责转换虚拟地址和物理地址。
2.2、操作系统上,操作系统增加了另一个核心组件:memory management,即内存管理模块,它管理物理内存、虚拟内存相关的一系列事务。
2.3、应用程序上,发明了一个叫做【进程】的模型,(注意)每个进程都用【完全一样的】虚拟地址空间,然而经由操作系统和硬件MMU协作,映射到不同的物理地址空间上。不同的【进程】,都有各自独立的物理内存空间,不用一些特殊手段,是无法访问别的进程的物理内存的。

3、现在,不同的应用程序,可以不关心底层的物理内存分配,也不关心CPU的协调共享了。然而还有一个问题存在:有一些程序,想要共享CPU,【并且还要共享同样的物理内存】,这时候,一个叫【线程】的模型就出现了,它们被包裹在进程里面,在调度器的管理下共享CPu,拥有同样的虚拟地址空间,同时也共享同一个物理地址空间,然而,它们无法越过包裹自己的进程,去访问别一个进程的物理地址空间。

4、进程之间怎样共享同一个物理地址空间呢?不同的系统方法各异,符合posix规范的操作系统都提供了一个接口,叫mmap,可以把一个物理地址空间映射到不同的进程中,由不同的进程来共享。

5、PS:在有的操作系统里,进程不是调度单位(即不能被调度器使用),线程是最基本的调度单位,调度器只调度线程,不调度进程,比如VxWorks

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是刘彦宏吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值