互斥鎖_zzhere2007

簡介:
互斥體實現了“互相排斥”(mutual exclusion)同步的簡單形式(所以名爲互斥體(mutex))。互斥體禁止多個線程同時進入受保護的代碼“臨界區”(critical section)。因此,在任意時刻,只有一個線程被允許進入這樣的代碼保護區。
任何線程在進入臨界區之前,必須獲取(acquire)與此區域相關聯的互斥體的所有權。如果已有另一線程擁有了臨界區的互斥體,其他線程就不能再進入其中。這些線程必須等待,直到當前的屬主線程釋放(release)該互斥體。
什麼時候需要使用互斥體呢?互斥體用於保護共享的易變代碼,也就是,全局或靜態數據。這樣的數據必須通過互斥體進行保護,以防止它們在多個線程同時訪問時損壞


Linux 2.6.26中mutex的定義:
struct mutex {
        /* 1: unlocked, 0: locked, negative: locked, possible waiters */
        atomic_t                  count;
        spinlock_t                wait_lock;
        struct list_head          wait_list;
#ifdef CONFIG_DEBUG_MUTEXES
        struct thread_info        *owner;
        const char                *name;
        void                      *magic;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
        struct lockdep_map         dep_map;
#endif
};

使用:

1  如果要定義一個靜態mutex型變量,應該使用DEFINE_MUTEX

2  如果在程序運行期要初始化一個mutex變量,可以使用mutex_init(mutex),mutex_init是個宏,在該宏定義的內部,會調用__mutex_init函數。

3  mutex上的P,V操作: 
                                       void mutex_lock(struct mutex *lock)
                                       void __sched mutex_unlock(struct mutex *lock)


原理:
對比前面的struct semaphore,struct mutex除了增加了幾個作爲debug用途的成員變量外,和semaphore幾乎長得一樣。但是mutex的引入主要是爲了提供互斥機制,以避免多個進程同時在一個臨界區中運行。
#define mutex_init(mutex)                                                   \
do {                                                                        \
        static struct lock_class_key __key;                                 \
                                                                            \ 
        __mutex_init((mutex), #mutex, &__key);                              \
} while (0)


__mutex_init定義如下:
void  __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
{
        atomic_set(&lock->count, 1);
        spin_lock_init(&lock->wait_lock);
        INIT_LIST_HEAD(&lock->wait_list);


        debug_mutex_init(lock, name, key);
}

     從__mutex_init的定義可以看出,在使用mutex_init宏來初始化一個mutex變量時,應該使用mutex的指針型。
從原理上講,mutex實際上是count=1情況下的semaphore,所以其PV操作應該和semaphore是一樣的。但是在實際的Linux代碼上,出於性能優化的角度,並非只是單純的重用down_interruptible和up的代碼。以ARM平臺的mutex_lock爲例,實際上是將mutex_lock分成兩部分實現:fast path和slow path,主要是基於這樣一個事實:在絕大多數情況下,試圖獲得互斥體的代碼總是可以成功獲得。所以Linux的代碼針對這一事實用ARM V6上的LDREX和STREX指令來實現fast path以期獲得最佳的執行性能。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章