计数和二进制信号量之间的区别

Ume*_*ooq 29 operating-system semaphore

Counting和二进制信号量有什么区别.

我在某处看到的是,两者都可以控制已请求资源的N个进程.两者都采取了自由状态.

二元信号量和计数信号量可以保护多少资源是否有任何限制?

两者都只允许一个进程一次使用一个资源......

还有其他区别吗?上述属性是否正确?

Fin*_*fin 33

实际上,这两种类型都用于同步对共享资源的访问,无论尝试访问的实体是进程还是线程.

区别如下:

二进制信号量是二进制的,它们只能有两个值; 一个表示进程/线程在关键部分(访问共享资源的代码)而其他人应该等待,另一个表示临界部分是空闲的.

另一方面,计算信号量需要两个以上的值,它们可以具有您想要的任何值.它们采用的最大值X允许X进程/线程同时访问共享资源.

有关详细信息,请查看此链接.
http://www.chibios.org/dokuwiki/doku.php?id=chibios:articles:semaphores_mutexes

编辑
计数信号量可以采用的最大值是您希望同时允许进入临界区的进程数.
同样,您可能希望排除特定资源,但您知道可以通过最大数量的进程(例如X)访问此资源,因此您可以设置值为X的计数信号量.

这将允许X进程同时访问该资源; 然而,过程X + 1必须等到关键部分中的一个过程结束.

  • 先生,您说过程可以同时使用资源!但是,信号量用于实现互斥,只有一个进程可以一次使用该资源.我是对还是错.计数信号量的最大值是什么意思? (3认同)
  • 好吧,计算信号量允许多个进程确实同时使用共享资源.有时,您希望同时允许关键部分中的两个进程,而不仅仅是一个进程,因为两个进程可以完成工作,而不会对程序的逻辑产生错误.我现在想不出一个例子,但那是基本的想法. (3认同)
  • 二进制信号量一次只允许一个进程同时访问共享.它们可以采用两个(因此是二进制)值,TAKEN或NAK-TAKEN. (2认同)

asp*_*100 8

构建并发程序有两个基本概念 - 同步和互斥.我们将看到这两种类型的锁(信号量通常是一种锁定机制)如何帮助我们实现同步和互斥.

信号量有两部分:计数器和等待访问特定资源的任务列表.信号量执行两个操作:wait(P)[这就像获取锁定],释放(V)[类似于释放锁定] - 这是人们可以对信号量执行的唯一两个操作.在二进制信号量中,计数器逻辑上介于0和1之间.您可以将其视为类似于具有两个值的锁:打开/关闭.计数信号量具有多个计数值.

重要的是要理解的是,信号量计数器会跟踪不必阻塞的任务数量,即它们可以取得进展.任务阻止,仅在计数器为零时将自己添加到信号量列表中.因此,如果任务无法进行,则会将任务添加到P()例程的列表中,并使用V()例程"释放".

现在,很明显看到二进制信号量如何用于解决同步和互斥 - 它们本质上是锁.

恩.同步:

thread A{
semaphore &s; //locks/semaphores are passed by reference! think about why this is so.
A(semaphore &s): s(s){} //constructor
foo(){
...
s.P();
;// some block of code B2
...
}

//thread B{
semaphore &s;
B(semaphore &s): s(s){} //constructor
foo(){
...
...
// some block of code B1
s.V();
..
}

main(){
semaphore s(0); // we start the semaphore at 0 (closed)
A a(s);
B b(s);
}
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,B2只能 B1完成执行后执行.假设线程A首先执行 - 获取sem.P(),并等待,因为计数器为0(关闭).线程B出现,完成B1,然后释放线程A - 然后完成B2.所以我们实现了同步.

现在让我们看一下二进制信号量的互斥:

thread mutual_ex{
semaphore &s;
mutual_ex(semaphore &s): s(s){} //constructor
foo(){
...
s.P();
//critical section
s.V();
...
...
s.P();
//critical section
s.V();
...

}

main(){
semaphore s(1);
mutual_ex m1(s);
mutual_ex m2(s);
}
Run Code Online (Sandbox Code Playgroud)

互斥也很简单 - m1和m2不能同时进入临界区.因此,每个线程使用相同的信号量为其两个关键部分提供互斥.现在,是否可以拥有更高的并发性?取决于关键部分.(想想如何使用信号量来实现互斥.提示:我是否只需要使用一个信号量?)

计数信号量:具有多个值的信号量.让我们来看看这意味着什么 - 一个具有多个值的锁?那么开放,封闭,......嗯.互斥或同步中的多阶段锁定有什么用?

让我们更容易两个:

使用计数信号量进行同步:假设您有3个任务 - 您希望在3之后执行#1和2.您将如何设计同步?

thread t1{
...
s.P();
//block of code B1

thread t2{
...
s.P();
//block of code B2

thread t3{
...
//block of code B3
s.V();
s.V();
}
Run Code Online (Sandbox Code Playgroud)

因此,如果你的信号量开始关闭,你确保t1和t2阻塞,被添加到信号量列表中.然后是所有重要的t3,完成其业务并释放t1和t2.他们被释放的顺序是什么?取决于信号量列表的实现.可以是FIFO,可以基于某些特定的优先级等.(注意:考虑如何安排你的P和V;如果你想要以某种特定的顺序执行t1和t2,并且你不知道信号量的实现)

(找出:如果V的数量大于P的数量,会发生什么?)

相互排斥使用计数信号量:我希望你为此构建自己的伪代码(让你更好地理解事物!) - 但基本概念是这样的:计数器的计数信号量= N允许N个任务自由地进入临界区.这意味着你有N个任务(或线程,如果你愿意)进入关键部分,但是第N + 1个任务被阻止(进入我们最喜欢的被阻止任务列表),只有当有人V是信号量时才通过至少一次.所以信号量计数器,而不是在0和1之间摆动,现在介于0和N之间,允许N个任务自由进入和退出,阻止任何人!

现在,你为什么需要这么奇怪的锁?是不是要让不止一个人访问资源的全部互斥点?认为.(提示 ......你的计算机中并不总是只有一个驱动器,你......?)

想一想:单独计算信号量可以实现互斥吗?如果您有10个资源实例,并且有10个线程进入(通过计数信号量)并尝试使用第一个实例,该怎么办?