进程与线程
进程与线程基础
在谈论线程、进程、时间片以及更神奇的调度概念之前,先打个比方。
我们首先要说明的就是线程与进程是如何工作的。最形象的理解就是将线程与进程想象为现实世界的东西。我们的比方如下:
进程想象为一个房子
先使用我们在日常生活中常见的东西——房子来开始线程与进程的比方。
房子其实就是一个容器,并且有其自己的特定属性(比如有几层楼、多少个房间等等)。
在这个比方中,我们可以看到房子靠其自身是不能做任何事的——它是一个被动的东西。而进程也是这样的。
线程想象为房子的住户
在房子中居住的人才是主动的对象,他们才是房子的使用者,在这里看电视、做饭、洗澡等等。
单线程情况
如果你是自己一个人住在房子里,你就知道可能的情况是这样的——你可以在任何时间在你的房子里面做任何事,因为这个房子里面除了你没有别人。如果你想听广播、洗澡或是吃午餐,不论是什么,只要去做就行了!
多线程情况
当有其他人开始在房中居住后,所有的这一切将有戏剧性的变化。比如你结婚了,你的配偶也会住在你的房子里面。这时你就不能在任何时间点都能直接冲进卫生间了,你先要检查你的配偶没有使用卫生间之后才能进去使用。
如果两个负责的成年人住在一个房子里面,你对安全就可以稍微马虎些。因为你知道另一个成年人会尊重你的空间,并且也不会让厨房起火等等。
这时放几个孩子进来,所有的境况就会开始变得有趣起来。
继续谈论进程与线程
就像房子占用了不动产的一个区域一样,一个进程占用了内存。同样,房子中的住户可以进入房子中的任何房间,进程中的线程也可以访问进程所占用的全部内存。如果一个线程分配了什么(妈妈出去买了一个游戏),那么其他的线程立刻就可以访问这个分配的东西(因为这个东西位于通用地址空间——因为这个游戏在家里)。同样的,如果进程分配了内存,全部线程就可以访问这个新内存。这里需要考虑的是这个新内存是否应该让进程中的全部线程可以访问。如果是的话,你就得让全部线程同步它们对内存的访问权。如果不是,架设只让特定的线程可以访问它。这时只有特定的线程可以访问它,就没有同步的必要了。
就像我们的日常生活一样,什么事都不是那么简单的。现在我们了解了一个基本特性(所有东西是共享的),现在看看更有趣的情况及其缘由。
互斥现象(Mutual Exclusion)
如果在房子中你想洗个澡,不过这是已经有人在使用卫生间了,你得先等等。对于线程来说是如何处理这种情况的呢?
线程是使用叫做互斥(mutual exclusion)的东西来处理这种情况的。它和你想象的十分相似,当一些线程同时访问特定资源时就会互斥。
如果你正在洗澡,你就想要独占卫生间。为了完成这个,你一般是进入卫生间之后在内部反锁卫生间的门。想要使用卫生间的其他人就会因为锁而阻挡在卫生间之外。当你完事后,你就会打开这个锁,其他人就可以使用卫生间了。
其实线程也是这样做的。它使用叫做互斥体(mutex)的对象。这个对象就像门上的锁——一旦一个线程将其锁上,其他线程就无法访问这个对象,直到现在的拥有线程释放它(或称解锁)。就像门锁一样,想要获得互斥体的线程将被阻挡。
在互斥体与门锁之间相同的特点还有一个,就是它们都是“建议性”的锁。如果一个线程不遵守互斥体使用的准则,这个保护机制就一点用也没有。在我们房子的比喻中,就像有人忽略了门锁的规则直接破墙而入一样。
优先级(Priorities)
假设现在卫生间正被反锁并且有很多人正在等着使用,这时该怎么办?显然这时这些人都在卫生间外面坐着等卫生间里面的人出来。这时的问题就是,如果门开了,谁先进去呢?
你可能想让等待时间最长的人先用是“公平”的、或让最年长的先用是“公平”的、或最高的、或最重要的等等是“公平”的。实际上是有好多种方法来判定什么是“公平”的。
在系统中,我们是使用两个参数来解决线程的这个问题的,这两个参数是:优先级以及等待时间的长短。
假如两个人同时出现在锁着门的卫生间前面。其中一个人有一个急迫的最后期限(比如已经晚了他要参加的会议),而另外一个人没有这个期限。是不是就应该让这个有最后期限的人先使用卫生间呢?是的,应该是这样的。这里唯一的问题是你如何确定谁更“重要”呢?这是可以通过分配优先级来实现的。那个有最后期限的人被分配了一个较高的优先级,而没有期限的被分配了较低的优先级。
对于线程我们可以做同样的事。一个线程会从其母线程继承其调度算法,但是我们可通过调用pthread_setschedparam()函数来修改其调度策略以及优先级(在有相应权限的时候才能这样做)。
如果很多线程都在等待,并且互斥体已经解锁,我们就会将互斥体交给等待线程中优先级最高的线程。那么假如两人的优先级相同,我们该怎么做呢?在这种情况下,让等待时间最长的人先进是“公平”的。其实在系统内核中,也是这样针对线程来实现的。在很多线程等待的时候,首先是根据优先级,其次再根据等待时间来选择线程的。
互斥体只是我们要遇到的同步对象的一种,后面还会介绍其他的同步对象。
Related posts:
近期评论