2012-07-17 125 views
6

在阅读关于二进制信号量和互斥我发现下面的差异:当互斥锁可用时,在哪里使用二进制信号量?

两者都可以具有值0和1,但互斥可以由已经获得互斥锁同一 线程被解锁。获取 互斥锁的线程可以具有优先级反转,以便在更高优先级 进程想要获取相同互斥体的情况下,而这不是具有二进制信号量的情况 。

所以我应该在哪里使用二进制信号?任何人都可以举一个例子吗?

编辑:我想我已经找到了两者的工作。基本上二进制信号提供同步,而互斥锁提供锁定机制。我从Galvin操作系统书中读了一些例子,使其更加清晰。在那里我找到二进制信号非常有用

回答

5

一个典型的情况是线程初始化,其中线程会从父线程所拥有的结构中读取。父线程需要等待新线程从结构中读取共享数据,然后才能让结构的生命周期结束(例如,通过离开它的作用域)。使用二进制信号量,您只需将信号量值初始化为零,然后在父级等待它时让孩子发布它。没有信号量,你需要一个互斥锁和条件变量以及更多丑陋的程序逻辑来使用它们。

1

用于使用信号量计数,而不是一个二值互斥典型的例子是,当你有可用资源的有限数量的是:a)可互换和b)多于一个。

举例来说,如果你想允许最多10个读者在一次访问一个数据库,你可以使用初始化至10的计数信号来限制对资源的访问。每个读者在访问资源之前都必须获取信号量,并减少可用的计数。一旦计数达到0(即10个读取器已经访问并且仍然使用数据库),所有其他读取器都被锁定。一旦读者结束,他们会将信号量计数返回1,表示他们不再使用该资源,而其他一些读者现在可以获得信号锁并取而代之。

然而,信号计数,就像所有其他的同步原语,有许多用例,它只是一个逆向思考的问题。您可能会发现,使用信号量可以更轻松,更直接地实现您使用互斥锁和其他逻辑解决的许多问题。互斥量是信号量的一个子集,也就是说,你可以用一个信号量完成任何你可以用一个互斥量完成的任务(简单地将计数设置为1),但是有一些事情可以用信号量来完成,不能用一个互斥体完成。

在一天结束的时候,任何一个同步原语一般是够做任何事(认为它为“图灵完备”的线程同步,以bastardize这个词)。但是,每种方法都适用于不同的应用程序,虽然您可以强制某人通过某种定制和附加胶水来执行您的出价,但有可能不同的同步原语更适合这项工作。

+3

OP询问二进制信号量与(总是二进制)互斥量,不计算信号量与互斥量。 – 2012-07-17 22:50:03

3

在几乎所有情况下,我都使用二进制信号量来发信号通知其他线程而不锁定。

使用的同步请求的简单例子:

线程1

Semaphore sem; 
request_to_thread2(&sem); // Function sending request to thread2 in any fashion 
sem.wait();    // Waiting request complete 

线程2

Semaphore *sem; 
process_request(sem);  // Process request from thread 1 
sem->post();    // Signal thread 1 that request is completed 

注意:您发布旗语在线程之前2处理您可以安全地设置线程1数据而无需任何额外的同步。