c-当互斥对象可用时,在哪里使用二进制信号量



在阅读二进制信号量和互斥时,我发现了以下区别:

两者都可以具有值0和1,但互斥对象可以由相同的已获取互斥锁的线程。获取互斥锁可以在优先级更高的情况下进行优先级反转进程想要获取相同的互斥,但事实并非如此使用二进制信号量。

那么我应该在哪里使用二进制信号量呢?有人能举个例子吗?

编辑:我想我已经弄清楚了两者的作用。基本上二进制信号量提供同步,而互斥提供锁定机制。我阅读了Galvin操作系统书中的一些例子,以使其更加清晰。

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

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

同步请求的简单用法示例:

线程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的数据,而无需任何额外的同步。

使用计数信号量而不是二进制互斥的典型例子是,当您有有限数量的可用资源时,a)可互换,b)不止一个。

例如,如果您希望一次最多允许10个读卡器访问数据库,则可以使用初始化为10的计数信号量来限制对资源的访问。每个读取器必须在访问资源之前获取信号量,从而递减可用计数。一旦计数达到0(即10个读者已经访问并仍在使用数据库),所有其他读者都将被锁定。一旦一个阅读器完成,他们就会将信号量计数增加一,以表明他们不再使用该资源,而其他一些阅读器现在可能会获得信号量锁并代替他们获得访问权限。

然而,计数信号量和所有其他同步原语一样,有许多用例,这只是一个跳出框框思考的问题。您可能会发现,使用信号量可以更容易、更直接地实现您习惯于使用互斥加上额外逻辑来解决的许多问题。互斥量是信号量的一个子集,也就是说,你可以用互斥量做的任何事情都可以用信号量做(只需将计数设置为1),但有些事情可以只用信号量做,而不能只用互斥量做。

在一天结束时,任何一个同步原语通常都足以做任何事情(将其视为线程同步的"turingcomplete",以诋毁这个词)。然而,每一个都适合不同的应用程序,虽然你可以通过一些定制和额外的胶水强制其中一个来完成你的出价,但不同的同步原语可能更适合这份工作。

最新更新