<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>路上 &#187; 信号变量</title>
	<atom:link href="http://www.speedvi.net/tag/%e4%bf%a1%e5%8f%b7%e5%8f%98%e9%87%8f/feed" rel="self" type="application/rss+xml" />
	<link>http://www.speedvi.net</link>
	<description>为者常成 行者常至</description>
	<lastBuildDate>Sat, 12 Jun 2010 06:30:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>进程与线程</title>
		<link>http://www.speedvi.net/2009/12/23/182.html</link>
		<comments>http://www.speedvi.net/2009/12/23/182.html#comments</comments>
		<pubDate>Wed, 23 Dec 2009 07:41:23 +0000</pubDate>
		<dc:creator>行者</dc:creator>
				<category><![CDATA[操作系统]]></category>
		<category><![CDATA[信号变量]]></category>
		<category><![CDATA[线程]]></category>
		<category><![CDATA[进程]]></category>

		<guid isPermaLink="false">http://www.speedvi.net/2009/12/23/182.html</guid>
		<description><![CDATA[信号变量(Semaphores) 　　现在把场景从卫生间转移到厨房，同一时间在厨房里面有几个人是可以接受的。在厨房里面，你也可能不想让所有的人同时进入。实际上，你可能是想让厨房中的人数保持在你设定的限度之内。 　　比如你不想在任何时间点厨房中的人数超过两个。这可以使用互斥体来实现么？根据我们的定义，是不行的。为什么不行就是我们的比喻中的一个非常有趣的问题。 计数为1的信号变量 　　卫生间可能遇到的情况是以下两种情况之一，有两种状态是互相关联的： 门是开的并且无人在房间内 门被锁住并且有一个人在房间内 &#160; 　　至于其他的组合是不存在的——房间内没人门是不会被锁住的（如果这样的话，我们该如何打开这个门呢？），而有人在房间里面门也是不能被打开的（如果打开的话，如何保证他们的隐私？）。这就是计数为一的信号变量的例子——在那个房间里面最多只能有一个人，或是一个线程在使用这个信号变量。 　　这里的关键就是我们描绘这个锁的方式。对于常见的卫生间门锁，你可以在内部开关这个锁——不存在可以在外部开锁的钥匙。实际上，互斥体的拥有是一个元素级的操作——当你正在执行获取互斥体的操作的时候，别的线程是没有机会获取它的，而产生有两个线程同时拥有互斥体的情况。在我们的这个房子的比喻中，这不是那么明显，因为人类比1与0要聪明多了。 　　我们举厨房的例子是要说明另一类不同的锁。 计数大于1的信号变量 　　假设我们在厨房安装了传统的需要钥匙开启的锁。这种锁的工作方式如下，如果你有一把对应的钥匙，你就可以打开这把锁并进入厨房里面。使用这个锁的所有人都同意当他们进入厨房之后就立刻从内部锁上这个门，这样外面的人必须在有钥匙的情况下才能进入厨房。 　　于是，控制厨房中的人数就变得很简单了——在门外挂两把钥匙，并且厨房永远是锁住的。如果有人想进入厨房的话，就先看看门外是否有一把挂着的钥匙。如果有的话，他们就可以拿到那把钥匙，打开厨房的门，进入厨房并使用这把钥匙锁门。 　　由于进入厨房的人必须带着他们的钥匙，我们就能够通过控制厨房门外的钥匙的数量，来控制在厨房中允许进入的人数。 　　对于线程来说，完成这个功能的就是信号变量（semaphore）。简单的信号变量的工作方式和互斥体是几乎一样的——你要么拥有互斥体从而可以访问资源，要么就不拥有互斥体从而不能访问资源。我们刚刚描述的信号变量是计数信号变量（counting semaphore）——它一直保持计数（就是线程可用的钥匙的数量）。 信号变量作为互斥体使用 　　我们刚刚问了个问题，就是能否使用互斥体来实现有计数功能的锁。对这个问题的答案是不能。是否还有其他的方式来完成该目的？另外能否将信号变量作为互斥体使用？ 　　是的。在一些操作系统中，它们实际上就是这样做的——它们没有互斥体，只有信号变量！也就没有让互斥体造成困扰的必要了。 　　要回答这个问题，请想一下你的房子的洗手间。盖房子的人如何来实现“互斥体”？我想你应该没有一把钥匙挂在墙上吧。 　　互斥体是一种特定用途的信号变量。如果你想让一个线程运行特定段代码，互斥体就是目前为止最有效的实现方式。 　　后面要提到的其他同步策略，包括了叫做条件变量、屏障以及睡眠量的东西。 Related posts:进程与线程 进程与线程基础 　　在谈论线程、进程、时间片以及更神奇的调度概念之前，先打个比方。 　　我们首先要说明的就是线程与进程是如何工作的。最形象的理解就是将线程与进程想象为现实世界的东西。我们的比方如下： 进程想象为一个房子 　　先使用我们在日常生活中常见的东西——房子来开始线程与进程的比方。 　　房子其实就是一个容器，并且有其自己的特定属性（比如有几层楼、多少个房间等等）。 　　在这个比方中，我们可以看到房子靠其自身是不能做任何事的——它是一个被动的东西。而进程也是这样的。 线程想象为房子的住户 　　在房子中居住的人才是主动的对象，他们才是房子的使用者，在这里看电视、做饭、洗澡等等。 &#160;... 系统内核的角色 　　我们前面的使用房子做的比喻对于解释同步的概念是非常合适的，但对系统中另一个重要方面就不合适了。在我们的比喻中，多个线程是同时运行的。可是，在实际的系统中，一般只有一个处理器，那么在一个时间点上只能运行一件“事”。 单处理器情况 　　下面看看在实际系统中的真实运行情况，在较“经济”的情况下，一个系统中只有一个中央处理器。这时，在任何时间点就只能有一个线程可以运行。系统内核使用数种规则来决定让哪个线程运行并运行该线程。 多处理器情况 　　如果你购买的计算机有多个、相同的CPU，并且这些CPU共享内存与设备，那么就可以说你有了一个SMP系统了（SMP是对称多处理器的简称，指系统中的这些处理器是一样的）。这时，可以同时运行的线程的数量就受限于CPU的个数了。由于一个CPU一次只能运行一个线程，在有多个CPU的情况下，多个线程就可以同步运行。 　　我们可以忽略CPU的个数，而抽象的设计系统能够让多个线程同步运行，虽然实际情况并不是这样。 内核作为仲裁者 　　那么谁来决定在指定时间哪个线程运行呢？这就是内核的工作职责。 　　内核决定了在特定时刻可以使用CPU的线程，并切换环境变量到那个线程。下面详细说明一下内核对CPU做了什么。 　　CPU有一定数量的寄存器（寄存器的具体数量依赖于处理器的类型）。当线程运行的时候，线程的一些信息就保存在这些寄存器里面，例如当前程序位置等等。... 内核状态 RUNNING 　　系统的运行状态简单的说就是表示有线程处于活动状态并在使用CPU。在多处理器系统中，可以有多个线程处于运行状态；在单处理器系统中，只能有一个线程处于运行状态。 READY 　　就绪状态表示线程现在可以运行了，只不过还未运行，因为现在有另外一个线程（同优先级或更高优先级）正在运行。如果有两个线程都有能力使用处理器，其中一个线程的优先级为10而另外一个线程的优先级为7，那么优先级为10的线程将进入运行状态而优先级为7的线程将进入就绪状态。 &#160; 阻塞状态(blocked states) 　　我们应该如何称呼阻塞状态？其实在系统中并不是只有一种阻塞状态，在实际系统中可以有数十种阻塞状态。 [...]


Related posts:<ol><li><a href='http://www.speedvi.net/2009/12/22/181.html' rel='bookmark' title='进程与线程'>进程与线程</a> <small>进程与线程基础 　　在谈论线程、进程、时间片以及更神奇的调度概念之前，先打个比方。 　　我们首先要说明的就是线程与进程是如何工作的。最形象的理解就是将线程与进程想象为现实世界的东西。我们的比方如下： 进程想象为一个房子 　　先使用我们在日常生活中常见的东西——房子来开始线程与进程的比方。 　　房子其实就是一个容器，并且有其自己的特定属性（比如有几层楼、多少个房间等等）。 　　在这个比方中，我们可以看到房子靠其自身是不能做任何事的——它是一个被动的东西。而进程也是这样的。 线程想象为房子的住户 　　在房子中居住的人才是主动的对象，他们才是房子的使用者，在这里看电视、做饭、洗澡等等。 &nbsp;...</small></li>
<li><a href='http://www.speedvi.net/2009/12/26/183.html' rel='bookmark' title='系统内核的角色'>系统内核的角色</a> <small>　　我们前面的使用房子做的比喻对于解释同步的概念是非常合适的，但对系统中另一个重要方面就不合适了。在我们的比喻中，多个线程是同时运行的。可是，在实际的系统中，一般只有一个处理器，那么在一个时间点上只能运行一件“事”。 单处理器情况 　　下面看看在实际系统中的真实运行情况，在较“经济”的情况下，一个系统中只有一个中央处理器。这时，在任何时间点就只能有一个线程可以运行。系统内核使用数种规则来决定让哪个线程运行并运行该线程。 多处理器情况 　　如果你购买的计算机有多个、相同的CPU，并且这些CPU共享内存与设备，那么就可以说你有了一个SMP系统了（SMP是对称多处理器的简称，指系统中的这些处理器是一样的）。这时，可以同时运行的线程的数量就受限于CPU的个数了。由于一个CPU一次只能运行一个线程，在有多个CPU的情况下，多个线程就可以同步运行。 　　我们可以忽略CPU的个数，而抽象的设计系统能够让多个线程同步运行，虽然实际情况并不是这样。 内核作为仲裁者 　　那么谁来决定在指定时间哪个线程运行呢？这就是内核的工作职责。 　　内核决定了在特定时刻可以使用CPU的线程，并切换环境变量到那个线程。下面详细说明一下内核对CPU做了什么。 　　CPU有一定数量的寄存器（寄存器的具体数量依赖于处理器的类型）。当线程运行的时候，线程的一些信息就保存在这些寄存器里面，例如当前程序位置等等。...</small></li>
<li><a href='http://www.speedvi.net/2009/12/27/184.html' rel='bookmark' title='内核状态'>内核状态</a> <small>RUNNING 　　系统的运行状态简单的说就是表示有线程处于活动状态并在使用CPU。在多处理器系统中，可以有多个线程处于运行状态；在单处理器系统中，只能有一个线程处于运行状态。 READY 　　就绪状态表示线程现在可以运行了，只不过还未运行，因为现在有另外一个线程（同优先级或更高优先级）正在运行。如果有两个线程都有能力使用处理器，其中一个线程的优先级为10而另外一个线程的优先级为7，那么优先级为10的线程将进入运行状态而优先级为7的线程将进入就绪状态。 &nbsp; 阻塞状态(blocked states) 　　我们应该如何称呼阻塞状态？其实在系统中并不是只有一种阻塞状态，在实际系统中可以有数十种阻塞状态。 　　为什么会有这么多种呢？因为内核一直保留着线程为何被阻塞的原因。 　　在前面我们已经讲到了两种阻塞状态——当线程等待互斥体时被阻塞，这时线程就是MUTEX状态。当一个线程由于等待信号变量而被阻塞的话，这时线程就是SEM状态。这些状态简要的说明了线程是阻塞于哪个队列或资源。...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<h5>信号变量(Semaphores)</h5>
<p>　　现在把场景从卫生间转移到厨房，同一时间在厨房里面有几个人是可以接受的。在厨房里面，你也可能不想让所有的人同时进入。实际上，你可能是想让厨房中的人数保持在你设定的限度之内。</p>
<p>　　比如你不想在任何时间点厨房中的人数超过两个。这可以使用互斥体来实现么？根据我们的定义，是不行的。为什么不行就是我们的比喻中的一个非常有趣的问题。</p>
<h6>计数为1的信号变量</h6>
<p>　　卫生间可能遇到的情况是以下两种情况之一，有两种状态是互相关联的：</p>
<ul>
<li>门是开的并且无人在房间内</li>
<li>门被锁住并且有一个人在房间内</li>
</ul>
<p>&nbsp;</p>
<p><span id="more-182"></span>
<p>　　至于其他的组合是不存在的——房间内没人门是不会被锁住的（如果这样的话，我们该如何打开这个门呢？），而有人在房间里面门也是不能被打开的（如果打开的话，如何保证他们的隐私？）。这就是计数为一的信号变量的例子——在那个房间里面最多只能有一个人，或是一个线程在使用这个信号变量。</p>
<p>　　这里的关键就是我们描绘这个锁的方式。对于常见的卫生间门锁，你可以在内部开关这个锁——不存在可以在外部开锁的钥匙。实际上，互斥体的拥有是一个元素级的操作——当你正在执行获取互斥体的操作的时候，别的线程是没有机会获取它的，而产生有两个线程同时拥有互斥体的情况。在我们的这个房子的比喻中，这不是那么明显，因为人类比1与0要聪明多了。</p>
<p>　　我们举厨房的例子是要说明另一类不同的锁。</p>
<h6>计数大于1的信号变量</h6>
<p>　　假设我们在厨房安装了传统的需要钥匙开启的锁。这种锁的工作方式如下，如果你有一把对应的钥匙，你就可以打开这把锁并进入厨房里面。使用这个锁的所有人都同意当他们进入厨房之后就立刻从内部锁上这个门，这样外面的人必须在有钥匙的情况下才能进入厨房。</p>
<p>　　于是，控制厨房中的人数就变得很简单了——在门外挂两把钥匙，并且厨房永远是锁住的。如果有人想进入厨房的话，就先看看门外是否有一把挂着的钥匙。如果有的话，他们就可以拿到那把钥匙，打开厨房的门，进入厨房并使用这把钥匙锁门。</p>
<p>　　由于进入厨房的人必须带着他们的钥匙，我们就能够通过控制厨房门外的钥匙的数量，来控制在厨房中允许进入的人数。</p>
<p>　　对于线程来说，完成这个功能的就是信号变量（semaphore）。简单的信号变量的工作方式和互斥体是几乎一样的——你要么拥有互斥体从而可以访问资源，要么就不拥有互斥体从而不能访问资源。我们刚刚描述的信号变量是计数信号变量（counting semaphore）——它一直保持计数（就是线程可用的钥匙的数量）。</p>
<h5>信号变量作为互斥体使用</h5>
<p>　　我们刚刚问了个问题，就是能否使用互斥体来实现有计数功能的锁。对这个问题的答案是不能。是否还有其他的方式来完成该目的？另外能否将信号变量作为互斥体使用？</p>
<p>　　是的。在一些操作系统中，它们实际上就是这样做的——它们没有互斥体，只有信号变量！也就没有让互斥体造成困扰的必要了。</p>
<p>　　要回答这个问题，请想一下你的房子的洗手间。盖房子的人如何来实现“互斥体”？我想你应该没有一把钥匙挂在墙上吧。</p>
<p>　　互斥体是一种特定用途的信号变量。如果你想让一个线程运行特定段代码，互斥体就是目前为止最有效的实现方式。</p>
<p>　　后面要提到的其他同步策略，包括了叫做条件变量、屏障以及睡眠量的东西。</p>


<p>Related posts:<ol><li><a href='http://www.speedvi.net/2009/12/22/181.html' rel='bookmark' title='进程与线程'>进程与线程</a> <small>进程与线程基础 　　在谈论线程、进程、时间片以及更神奇的调度概念之前，先打个比方。 　　我们首先要说明的就是线程与进程是如何工作的。最形象的理解就是将线程与进程想象为现实世界的东西。我们的比方如下： 进程想象为一个房子 　　先使用我们在日常生活中常见的东西——房子来开始线程与进程的比方。 　　房子其实就是一个容器，并且有其自己的特定属性（比如有几层楼、多少个房间等等）。 　　在这个比方中，我们可以看到房子靠其自身是不能做任何事的——它是一个被动的东西。而进程也是这样的。 线程想象为房子的住户 　　在房子中居住的人才是主动的对象，他们才是房子的使用者，在这里看电视、做饭、洗澡等等。 &nbsp;...</small></li>
<li><a href='http://www.speedvi.net/2009/12/26/183.html' rel='bookmark' title='系统内核的角色'>系统内核的角色</a> <small>　　我们前面的使用房子做的比喻对于解释同步的概念是非常合适的，但对系统中另一个重要方面就不合适了。在我们的比喻中，多个线程是同时运行的。可是，在实际的系统中，一般只有一个处理器，那么在一个时间点上只能运行一件“事”。 单处理器情况 　　下面看看在实际系统中的真实运行情况，在较“经济”的情况下，一个系统中只有一个中央处理器。这时，在任何时间点就只能有一个线程可以运行。系统内核使用数种规则来决定让哪个线程运行并运行该线程。 多处理器情况 　　如果你购买的计算机有多个、相同的CPU，并且这些CPU共享内存与设备，那么就可以说你有了一个SMP系统了（SMP是对称多处理器的简称，指系统中的这些处理器是一样的）。这时，可以同时运行的线程的数量就受限于CPU的个数了。由于一个CPU一次只能运行一个线程，在有多个CPU的情况下，多个线程就可以同步运行。 　　我们可以忽略CPU的个数，而抽象的设计系统能够让多个线程同步运行，虽然实际情况并不是这样。 内核作为仲裁者 　　那么谁来决定在指定时间哪个线程运行呢？这就是内核的工作职责。 　　内核决定了在特定时刻可以使用CPU的线程，并切换环境变量到那个线程。下面详细说明一下内核对CPU做了什么。 　　CPU有一定数量的寄存器（寄存器的具体数量依赖于处理器的类型）。当线程运行的时候，线程的一些信息就保存在这些寄存器里面，例如当前程序位置等等。...</small></li>
<li><a href='http://www.speedvi.net/2009/12/27/184.html' rel='bookmark' title='内核状态'>内核状态</a> <small>RUNNING 　　系统的运行状态简单的说就是表示有线程处于活动状态并在使用CPU。在多处理器系统中，可以有多个线程处于运行状态；在单处理器系统中，只能有一个线程处于运行状态。 READY 　　就绪状态表示线程现在可以运行了，只不过还未运行，因为现在有另外一个线程（同优先级或更高优先级）正在运行。如果有两个线程都有能力使用处理器，其中一个线程的优先级为10而另外一个线程的优先级为7，那么优先级为10的线程将进入运行状态而优先级为7的线程将进入就绪状态。 &nbsp; 阻塞状态(blocked states) 　　我们应该如何称呼阻塞状态？其实在系统中并不是只有一种阻塞状态，在实际系统中可以有数十种阻塞状态。 　　为什么会有这么多种呢？因为内核一直保留着线程为何被阻塞的原因。 　　在前面我们已经讲到了两种阻塞状态——当线程等待互斥体时被阻塞，这时线程就是MUTEX状态。当一个线程由于等待信号变量而被阻塞的话，这时线程就是SEM状态。这些状态简要的说明了线程是阻塞于哪个队列或资源。...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.speedvi.net/2009/12/23/182.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

