线程和进程基础——翻译文

前言

所有的内容均来自:http://www.qnx.com/developers/docs/6.4.1/neutrino/getting_started/s1_procs.html
这是一篇很棒的介绍进程和线程的文章,本文属于自己感兴趣翻译过来的文章,有兴趣的读者也可以去拜读一下原文。

进程和线程基础

在我们开始讨论线程,进程,时间片以及各种神奇的“调度机制”之前,先来建立一个类比。

我首先要做的就是说明线程和进程是如何工作的。我能想到的最好的方式(不涉及实时系统的设计)就是把线程和进程想象成一些实际的情形。

进程就像是一个房子

让我们用一个常规的、日常的物品来模拟进程和线程——房子。

房子实际上是一个容器,具有一定的属性(例如楼面面积,房间数目等等)。

如果你能这样看待,那么你就会发现房子不会自己主动去做任何事——它只是一个被动的物体。这就是进程实际上所担任的角色。我们待会儿会讨论到。

线程就像居住者

住在房子里的人们是活跃的对象——他们使用不同的房间,看电视,做饭,洗澡等等。我们很快就会发现这就是线程的行为模式。

单线程

如果你曾经一个人生活过,那么你就会知道这是一种什么感觉——你知道,你可以在任何时候在家里做任何你想做的事,因为房子里没有其他人。如果你想打开立体声音响,使用洗手间,吃晚餐,随便你,你只要继续做就行了。

多线程

当你把另一个人加入房子时,事情会发生戏剧性的变化。假设你结婚了,所以现在你的配偶也住在那里。你不能在任何一个特定的时间进入洗手间,你需要先检查一下,确保你的配偶不在里面!

如果你有两个负责任的成年人住在一所房子里,一般来说,你可能会对“安全”相当松懈-因为你知道另一个大人会尊重你的空间,不会试图放火烧厨房(故意!)等等。

现在,把几个孩子扔到一起,突然之间事情变得有趣多了。

回到进程和线程

就像房子占据了房地产的一部分一样,进程也会占据一定的内存。就像房子的住户可以自由进入任何他们想要的房间一样,一个进程的线程都可以访问这个内存。如果一个线程分配了一些东西(妈妈出去买了一个游戏),所有其他的线程都能立即访问它(因为它存在于公共地址空间-它在房子里)。同样,如果进程分配内存,那么这个新内存也可以用于所有线程。这里的技巧是,确认内存是否应该对进程中的所有线程都可用。如果是,那么您需要让所有线程同步它们对它的访问。如果不是,那么我们假设它是特定于特定线程的。在这种情况下,因为只有该线程才能访问它,所以我们可以假定不需要同步-线程不会自行启动!

正如我们从日常生活中所知道的,事情并不那么简单。现在我们已经了解了基本特性(要点:所有内容都是共享的),让我们来看看事情变得更有趣的地方,以及为什么。

下图显示了我们将代表线程和进程的方式。进程是圆,表示“容器”概念(地址空间),三个squigley lines(不知道是什么)是线程。你会在书中看到这样的图表。

进程作为线程的容器

相互排斥

如果你想洗个澡,而且有人已经在用浴室,你就得等着。线程是如何处理这个的?

它用的是一种叫做互斥的操作。它几乎意味着你所想的-当涉及到特定的资源时,许多线程是互斥的。

如果你正在洗澡,你想要独占浴室。要做到这一点,你通常会进入浴室并把门从里面锁起来。任何想使用浴室的人都会被锁上的。当你完成任务时,你会打开门,让其他人进入。

这就是线程所做的。线程使用一个名为互斥的对象(相互排斥的缩写)。这个对象就像门上的锁-一旦线程拥有互斥锁,没有其他线程可以获得互斥锁,直到拥有的线程释放(解锁)它。就像门锁一样,等待获得互斥锁的线程将被禁止。

互斥锁和门锁的另一个有趣的相同点是互斥锁实际上是一个“咨询”锁。如果一个线程不符合使用互斥锁的约定,那么保护就没有用了。在我们的房子比喻中,这就像有人通过墙壁闯进厕所,无视了门和锁的约定。

优先级

如果浴室现在锁着,有许多人在等着使用它,那该怎么做?显然,所有的人都坐在外面,等着在浴室里的人出去。真正的问题是,“当门打开时会发生什么?谁能下一个进入?“

你会认为,让等了最长的时间得那个成为下一个是“公平的”。或者,让最年长的人成为下一个是“公平”的。或者最高的。或者最重要的。有许多方法可以确定什么是“公平”。

我们通过线程的两个因素来解决这个问题:优先级和等待长度。

假设两个人同时出现在(上锁的)卫生间的门前。其中一人有一个紧迫的事情(他们开会已经很晚了),而另一个却没有。让那个时间紧迫的人下一次进去,是不是很有道理呢?当然会了。唯一的问题是你如何决定谁更“重要”。这可以通过分配优先级来完成(让我们使用一个像中微子(Neutrino)这样的数字,是最低的可用优先级,255是这个版本中的最高值)。房子里有紧迫事情的人将被给予更高的优先权,而那些不被优先考虑的人将被给予较低的优先权。

和线程一样。线程继承其父线程的调度算法,但可以调用pthread_setschedparam()来更改其调度策略和优先级(如果它有权限这样做)。

如果有多个线程等待,并且互斥锁被解锁,我们将把互斥锁给予等待线程中最高优先级的那个。但是,假设两个人都具有相同的优先级。现在你要做什么?好吧,在这种情况下,让等待最长的人下一个或许是“公平的”。这不仅是“公平的”,而且也是在内核所做的。在一堆线程等待的情况下,我们首先是按优先级等级来决定,其次是等待长度。

互斥量肯定不是我们将遇到的唯一的同步对象。让我们看看其他的。

信号量

让我们从浴室搬到厨房,因为这是一个在社会上可以接受同时容纳一个人以上的地点。在厨房里,你可能不想让每个人都在里面。事实上,你可能想要限制你的厨房里所能容纳的人数(太多的厨师,等等)。

假设你不想同时拥有两个以上的人。你能用互斥体来实现吗?这不是我们定义的。为什么不呢?这实际上是一个非常有趣的问题。让我们把它分成几个步骤。

数量为1的信号量

浴室可以有两种情况中的一种,两种状态相互联系(with two states that go hand-in-hand with each other):

  • 门没有锁,房间里没有人
  • 门是锁着的,房间里有一个人

没有其他的组合是可能的-当房间里没人的时候不能上锁(不然我们怎么解锁?),而且当有人在房间里时不能解锁(他们怎么保证他们的隐私?)。这是一个信号量的示例,其计数为1-最多只能有一个人在该房间,或者一个线程使用信号量。

这里的关键(key)(请原谅双关语)是我们描述锁的方式。在典型的浴室锁中,你可以锁定和解锁它只有从内部-没有外部可访问的钥匙。实际上,这意味着互斥对象的所有权是一个原子操作-在获取互斥锁的过程中,没有可能有其他线程得到它,结果是你一直拥有互斥锁。在我们的房子比喻中,这是不太明显的,因为人类比计算机聪明太多(smarter than ones and zeros)。

数量大于1的信号量

假设我们在厨房安装了传统的钥匙锁。这个锁的工作方式是,如果你有一个钥匙,你可以打开门并进入。任何使用这个锁的人都同意,当他们进去时,他们会立即把门从里面锁起来,这样外面的人总是需要钥匙。

现在,控制我们想要多少人在厨房里-把两个钥匙挂在门外,这就变成了一件简单的事情!厨房总是锁着的。当有人想走进厨房时,他们会发现门外有一把钥匙。如果是的话,他们就带着它,打开厨房的门,进去,用钥匙锁上门。

因为进入厨房的人在厨房的时候一定要带钥匙,所以我们可以通过限制门上的钥匙的数量来直接控制进入厨房的人数。

对于线程,这就需要通过信号量来完成了。“普通”信号量就像一个互斥体一样工作-你要么拥有互斥量,在这种情况下,你可以访问资源,或者你没有,在这种情况下,你没有访问权限。我们刚才在厨房描述的信号量是一个计数信号,它保持计数的记录(线程所允许的keys数量)。

互斥的信号量

我们只是问了一个问题“你能用一个互斥量来做吗?”关于用计数实现一个锁,答案是否定的,反过来呢?我们能用信号量作为互斥量吗?

是的。事实上,在某些操作系统中,这正是他们所做的-他们没有互斥锁,只有信号量!那么,为什么要麻烦互斥锁呢?

要回答这个问题,看看你的洗手间。你的房子的建造者是如何实现“互斥”的?我猜你没有挂在墙上的钥匙!

互斥锁(Mutexes)是一个“特殊用途”信号量。如果您希望一个线程在特定的代码段中运行,那么互斥锁是迄今为止最有效的实现。

结束语

这篇文章真的可谓是生动有趣,把线程和进程用了生活中的比喻来描述,很是深刻。原文中的描述虽然简单,但有些单词还是有些拿不准,我都打出来了,甚至有一些描述有些生硬,如有错误,请指出。


欢迎转载,转载请注明出处!
简书ID:@我没有三颗心脏
github:wmyskxz
欢迎关注公众微信号:wmyskxz
分享自己的学习 & 学习资料 & 生活
想要交流的朋友也可以加qq群:3382693

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 又来到了一个老生常谈的问题,应用层软件开发的程序员要不要了解和深入学习操作系统呢? 今天就这个问题开始,来谈谈操...
    tangsl阅读 4,004评论 0 23
  • 一、进程和线程 进程 进程就是一个执行中的程序实例,每个进程都有自己独立的一块内存空间,一个进程中可以有多个线程。...
    阿敏其人阅读 2,566评论 0 13
  • 引用自多线程编程指南应用程序里面多个线程的存在引发了多个执行线程安全访问资源的潜在问题。两个线程同时修改同一资源有...
    Mitchell阅读 1,929评论 1 7
  • 在上篇中,我们已经讨论过如何去实现一个 Map 了,并且也讨论了诸多优化点。在下篇中,我们将继续讨论如何实现一个线...
    一缕殇流化隐半边冰霜阅读 7,543评论 5 41
  • 闲暇时 低下头 想你 我心荒凉 又有点苦涩 像嚼黄连一样 每当“衣锦还乡” 目睹那群山叠嶂 长满野花的山岗 曾一起...
    坦人阅读 224评论 1 3