<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=Semaphore</id>
	<title>Semaphore - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=Semaphore"/>
	<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=Semaphore&amp;action=history"/>
	<updated>2026-04-04T11:42:06Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>http://wiki.foofun.cn//index.php?title=Semaphore&amp;diff=852&amp;oldid=prev</id>
		<title>Zhang3：创建页面，内容为“'''信号量（semaphore）''' 是一种同步原始数据类型。  从程序员的角度来看，它是一种不透明的数据类型，有两个定义的操作，通常称为'''wait'''和'''signal'''。（译者注：可以理解为和PV操作对应，wait是P操作-尝试申请资源，signal是V操作-释放资源）  有两种类型的信号量--“二进制信号量”和“计数信号量”。  == 计数信号量 == 最常…”</title>
		<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=Semaphore&amp;diff=852&amp;oldid=prev"/>
		<updated>2022-03-14T03:01:33Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“&amp;#039;&amp;#039;&amp;#039;信号量（semaphore）&amp;#039;&amp;#039;&amp;#039; 是一种&lt;a href=&quot;/index.php?title=%E5%88%86%E7%B1%BB:Synchronization&quot; title=&quot;分类:Synchronization&quot;&gt;同步&lt;/a&gt;原始数据类型。  从程序员的角度来看，它是一种不透明的数据类型，有两个定义的操作，通常称为&amp;#039;&amp;#039;&amp;#039;wait&amp;#039;&amp;#039;&amp;#039;和&amp;#039;&amp;#039;&amp;#039;signal&amp;#039;&amp;#039;&amp;#039;。（译者注：可以理解为和PV操作对应，wait是P操作-尝试申请资源，signal是V操作-释放资源）  有两种类型的信号量--“二进制信号量”和“计数信号量”。  == 计数信号量 == 最常…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;'''信号量（semaphore）''' 是一种[[:Category:Synchronization|同步]]原始数据类型。  从程序员的角度来看，它是一种不透明的数据类型，有两个定义的操作，通常称为'''wait'''和'''signal'''。（译者注：可以理解为和PV操作对应，wait是P操作-尝试申请资源，signal是V操作-释放资源）  有两种类型的信号量--“二进制信号量”和“计数信号量”。&lt;br /&gt;
&lt;br /&gt;
== 计数信号量 ==&lt;br /&gt;
最常见的信号量类型是计数信号量。  可以将其视为单个整数变量。  当调用 '''signal''' 方法时，变量被[[atomic operation|原子]] 递增。  当调用'''wait'''方法时，进程将持续等待直到变量达到非零值，然后在返回之前对其进行原子递减。&lt;br /&gt;
&lt;br /&gt;
==二进制信号量==&lt;br /&gt;
二进制信号量 (也称为Mutex-互斥) 就像计数信号量，不同之处在于 '''signal''' 方法将信号量的值设置为1，而不是将其递增。&lt;br /&gt;
&lt;br /&gt;
==用法==&lt;br /&gt;
二进制信号量最常用于保证[[Mutual Exclusion|互斥]]。 在这种情况下，信号量值被初始化为1，并且一个应用程序即将进入代码的互斥部分调用 '''wait'''， 然后在退出代码后调用'''signal'''。&lt;br /&gt;
&lt;br /&gt;
计数信号量可以用作实现许多同步模型的构建基础模块。 这方面的典型示例是静态分配的队列，如下面的示例所示。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
Message queue[N];&lt;br /&gt;
Semaphore slots = new Semaphore(N);&lt;br /&gt;
Semaphore messages = new Semaphore(0);&lt;br /&gt;
int last_read = 0&lt;br /&gt;
int last_written = 0;&lt;br /&gt;
&lt;br /&gt;
Message get()&lt;br /&gt;
{&lt;br /&gt;
   Message m;&lt;br /&gt;
   messages.wait();&lt;br /&gt;
   &lt;br /&gt;
   m = queue[last_read];&lt;br /&gt;
   last_read = (last_read+1)%N;&lt;br /&gt;
  &lt;br /&gt;
   slots.signal();&lt;br /&gt;
   return m;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void put(Message m)&lt;br /&gt;
{&lt;br /&gt;
   slots.wait();&lt;br /&gt;
   &lt;br /&gt;
   queue[last_written] = m;&lt;br /&gt;
   last_written = (last_written+1)%N;&lt;br /&gt;
   &lt;br /&gt;
   messages.signal();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在上面的示例中，这些函数可以使用错误代码来告诉调用方数组何时没有空间，以及队列何时为空 (或断言，由于空间不足而终止程序/使内核崩溃，并试图从空队列中get()内容)。 但是，在许多情况下，您只是希望当前线程阻塞，直到可以执行实际请求为止。 在这些情况下，你需要一个信号量。&lt;br /&gt;
&lt;br /&gt;
有很多(很多很多)算法使用信号量作为同步原语。 当信号量用于同步同一进程的多个线程时，这种算法通常会结合二进制 (互斥) 和计数信号量。 这是因为操纵数据结构的代码仍然必须是互斥的，即使使用信号量来控制资源使用。&lt;br /&gt;
&lt;br /&gt;
== 实现 ==&lt;br /&gt;
虽然信号量的描述非常简单，但实现并不像最初听起来那样容易。  首先，确保这两种方法原子化运行并不总是容易的； 其次，出于效率的目的，应该从调度器队列中移除对值为0的信号量调用'''wait''' 的线程， 并且只有在信号量发出信号（signalled，译者注：V操作）时才再次添加。&lt;br /&gt;
&lt;br /&gt;
因此，信号量的通常实现是作为内核级对象，它使用另一种更原始的锁定形式（例如[[spinlock|自旋锁]]），以确保一次只能有一个线程访问它。  除了整数变量之外，它还包含一个等待访问的线程队列。  每当调用 '''signal''' 时，在递增变量后立即唤醒并重新安排队列前端的线程 （或者，在某些情况下，变量永远不会递增，唤醒的线程跳过递减的阶段； 这样做可以确保唤醒已有线程进行，而不是某些新到达的线程来抢占)。  每当 '''wait''' 无法立即进行时，当前线程将被挂起并在适当的位置添加到队列中 （例如，在末端，或在与线程优先级正确的位置）。&lt;br /&gt;
&lt;br /&gt;
注意，这里有一个典型的竞争条件，称为lost wake-up（无法唤醒问题）问题。 有关此问题的解决方案，请阅读本文 http://www.linuxjournal.com/article/8144。&lt;br /&gt;
&lt;br /&gt;
==另见==&lt;br /&gt;
&lt;br /&gt;
===相关文章===&lt;br /&gt;
&lt;br /&gt;
=== 论坛主题 ===&lt;br /&gt;
&lt;br /&gt;
===外部链接===&lt;br /&gt;
* [[wikipedia:Semaphore_(programming)|Semaphore]] on Wikipedia&lt;br /&gt;
&lt;br /&gt;
[[Category:Synchronization]]&lt;br /&gt;
[[Category:IPC]]&lt;/div&gt;</summary>
		<author><name>Zhang3</name></author>
	</entry>
</feed>