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与MutexC# Semaphore Classhttp://msdn.microsoft.com/en-us/library/system.threading.semaphore.aspx wiki Semaphore (programming) http://en./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 |
|
来自: champion_xu > 《Signal》