Semaphore与Mutex的关系

来源:互联网 发布:淘宝卖的人参是真的吗 编辑:程序博客网 时间:2024/05/14 08:14


Semaphore与Mutex的关系



在多线程编程中,经常使用到如Semaphore或Mutex等许多线程间同步用的工具,但是Mutex和Semaphore的区别一直让
人困惑在Pintos Project的实践中,逐渐摸索到一些其中的区别。以下的实现来自Pintos Project。
一、Semaphore
1. 信号量是一个非负整数,具有两种原子操作:
a. P操作:也称Down操作。等待信号量变为正数,而后减少信号量;
b. V操作:也称Up操作。增加信号量,唤醒等待队列中的进程
/* A counting semaphore. */
struct semaphore
{
unsigned value;              /* Current value. */
struct list waiters;           /* List of waiting threads. */
};
void sema_init (struct semaphore *sema, unsigned value)
{
ASSERT (sema != NULL);
sema->value = value;
list_init (&sema->waiters);
}
2. P操作:
P操作等待信号量的值变为正数,而后减少信号量的值,并将此进程列入等待进程列表,阻塞当前进程
void sema_down (struct semaphore *sema)
{
enum intr_level old_level;
ASSERT (sema != NULL);
ASSERT (!intr_context ());
old_level = intr_disable ();
while (sema->value == 0)
{
list_push_back (&sema->waiters, &thread_current ()->elem);
thread_block ();
}
sema->value--;
intr_set_level (old_level);
}

3. V操作:
V操作增加信号量的值,并从等待队列中,去除队列顶部的进程,唤醒其继续执行
void sema_up (struct semaphore *sema)
{
enum intr_level old_level;
ASSERT (sema != NULL);
old_level = intr_disable ();
if (!list_empty (&sema->waiters))
thread_unblock (list_entry (list_pop_front (&sema->waiters),
struct thread, elem));
sema->value++;
intr_set_level (old_level);
}
二、Mutex
在Pintos Project中,Mutex用Lock实现。
1. 一个Lock被确定的一个线程拥有,只有拥有者线程才能操作Lock:
/* Lock. */
struct lock
{
struct thread *holder;               /* Thread holding lock (for debugging). */
struct semaphore semaphore;  /* Binary semaphore controlling access. */
};
void lock_init (struct lock *lock)
{
ASSERT (lock != NULL);
lock->holder = NULL;
sema_init (&lock->semaphore, 1);
}
2. Acquire操作:
请求一个Lock,该Lock必须由当前线程拥有。使得当前线程进入挂起状态,直到该Lock被释放。
void lock_acquire (struct lock *lock)
{
ASSERT (lock != NULL);
ASSERT (!intr_context ());
ASSERT (!lock_held_by_current_thread (lock));
sema_down (&lock->semaphore);
lock->holder = thread_current ();
printf("%d", &thread_current().priority);
}
3. Release操作:
释放一个Lock,该Lock必须由当前线程拥有。
void lock_release (struct lock *lock)
{
ASSERT (lock != NULL);
ASSERT (lock_held_by_current_thread (lock));
lock->holder = NULL;
sema_up (&lock->semaphore);
}
三、区别和联系
1. 初始状态不一样:Mutex的初始值是1(表示锁可用),而Semaphore的初始值是0,随后的操作基本一
样。
2.
用法不一样:Mutex的使用者必须为同一个线程,即必须成对使用。而Semaphore可以由不同的线程进行P和V操作,即可以由一个线程不停的P一个
资源,而另一个线程不停地V一个资源,故可以应用于生产者-消费者模型等资源同步的场合。因此,Mutex又不同于一个二值的Semaphore。


semaphore与Mutex

C# Semaphore Class
http://msdn.microsoft.com/en-us/library/system.threading.semaphore.aspx

wiki
Semaphore (programming)
http://en.wikipedia.org/wiki/Semaphore_%28programming%29


理解Semaphore和Mutex
Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。一般的用法是用于串行化对critical section代码的访问,保证这段代码不会被并行的运行。

 

Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。对于N=1的情况,称为binary semaphore。一般的用法是,用于限制对于某一资源的同时访问。

 

Binary semaphore与Mutex的差异:

在有的系统中Binary semaphore与Mutex是没有差异的。在有的系统上,主要的差异是mutex一定要由获得锁的进程来释放。而semaphore可以由其它进程释放(这时的semaphore实际就是个原子的变量,大家可以加或减),因此semaphore可以用于进程间同步。Semaphore的同步功能是所有系统都支持的,而Mutex能否由其他进程释放则未定,因此建议mutex只用于保护critical section。而semaphore则用于保护某变量,或者同步。

 

另一个概念是spin lock,这是一个内核态概念。spin lock与semaphore的主要区别是spin lock是busy waiting,而semaphore是sleep。对于可以sleep的进程来说,busy waiting当然没有意义。对于单CPU的系统,busy waiting当然更没意义(没有CPU可以释放锁)。因此,只有多CPU的内核态非进程空间,才会用到spin lock。Linux kernel的spin lock在非SMP的情况下,只是关irq,没有别的操作,用于确保该段程序的运行不会被打断。其实也就是类似mutex的作用,串行化对 critical section的访问。但是mutex不能保护中断的打断,也不能在中断处理程序中被调用。而spin lock也一般没有必要用于可以sleep的进程空间。

用semaphore实现mutex

以及 用mutex 实现semaphore

http://bbs.chinaunix.net/viewthread.php?tid=963707
原创粉丝点击