1. 程式人生 > >互斥鎖mutex

互斥鎖mutex

在訊號量最後的部分說,當count=1的時候可以用訊號量實現互斥。在早期的Linux版本中就是當count=1來實現mutex的。 核心重新定義了一個新的資料結構 struct mutex, 將其稱為互斥鎖或者互斥體。同時對訊號量的DOWN和UP操作針對struct mutex做了修改。

互斥鎖的定義和初始化

因為struct mutex的定義中有一些除錯相關的成員,在這裡去掉除錯資訊。
  1. /* 
  2.  * Simple, straightforward mutexes with strict semantics: 
  3.  * 
  4.  * - only one task can hold the mutex at a time 
  5.  * - only the owner can unlock the mutex 
  6.  * - multiple unlocks are not permitted 
  7.  * - recursive locking is not permitted
     
  8.  * - a mutex object must be initialized via the API 
  9.  * - a mutex object must not be initialized via memset or copying 
  10.  * - task may not exit with mutex held 
  11.  * - memory areas where held locks reside must not be freed 
  12.  * - held mutexes must not be reinitialized 
  13.  * - mutexes may not be used in hardware or software interrupt
     
  14.  *   contexts such as tasklets and timers 
  15.  * 
  16.  * These semantics are fully enforced when DEBUG_MUTEXES is 
  17.  * enabled. Furthermore, besides enforcing the above rules, the mutex 
  18.  * debugging code also implements a number of additional features 
  19.  * that make lock debugging easier and faster:
     
  20.  * 
  21.  * - uses symbolic names of mutexes, whenever they are printed in debug output 
  22.  * - point-of-acquire tracking, symbolic lookup of function names 
  23.  * - list of all locks held in the system, printout of them 
  24.  * - owner tracking 
  25.  * - detects self-recursing locks and prints out all relevant info 
  26.  * - detects multi-task circular deadlocks and prints out all affected 
  27.  *   locks and tasks (and only those tasks) 
  28.  */
  29. struct mutex {  
  30.     /* 1: unlocked, 0: locked, negative: locked, possible waiters */
  31.     atomic_t        count;  
  32.     spinlock_t      wait_lock;  
  33.     struct list_head    wait_list;  
  34. };  
這裡必須要對註釋詳細說明一下,其中說明一些mutex的嚴格語法資訊: a.  在同一時刻只能有一個task獲得互斥鎖 b.  只有鎖的獲得者才能有資格釋放鎖 c.  多處釋放鎖是不允許的 d.  遞迴獲取鎖是不允許的 e.  互斥鎖必須使用系統的API初始化,不允許直接操作使用memset/memcpy f.   獲得鎖的task是不允許退出 g.  持有鎖駐留的記憶體區域不能被釋放 h. 互斥鎖不能用於中斷上下文中, spin_lock是可以用於中斷上下文的 。 再解釋下struct mutex成員的含義: count:        count是一個原子變數,(關於原子變數不懂的,可以看前面的原子變數文章)。 當count=1代表資源可用,等於0代表資源不可用,加鎖狀態。 負值代表有等待者。 wait_lock: 是一個自旋鎖變數, 用於對wait_list的操作變為原子變數 wait_list  : 用於管理那些在獲取mutex的程序,在無法獲取互斥鎖的時候,進入wait_List睡眠。 是不是和semaphore一樣。 既然一樣,互斥鎖的定義和初始化也不能直接操作,必須使用系統提供的API: 定義一個靜態的struct mutex變數的同時初始化的方法:
  1. #define __MUTEX_INITIALIZER(lockname) \
  2.         { .count = ATOMIC_INIT(1) \  
  3.         , .wait_lock = __SPIN_LOCK_UNLOCKED(lockname.wait_lock) \  
  4.         , .wait_list = LIST_HEAD_INIT(lockname.wait_list) \  
  5.         __DEBUG_MUTEX_INITIALIZER(lockname) \  
  6.         __DEP_MAP_MUTEX_INITIALIZER(lockname) }  
  7. #define DEFINE_MUTEX(mutexname) \
  8.     struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)  

如果需要初始化一個互斥鎖,則可以使用mutex_init巨集:
  1. /** 
  2.  * mutex_init - initialize the mutex 
  3.  * @mutex: the mutex to be initialized 
  4.  * 
  5.  * Initialize the mutex to unlocked state. 
  6.  * 
  7.  * It is not allowed to initialize an already locked mutex. 
  8.  */
  9. # define mutex_init(mutex) \
  10. do {                            \  
  11.     staticstruct lock_class_key __key;     \  
  12.                             \  
  13.     __mutex_init((mutex), #mutex, &__key);      \  
  14. while (0)  
  15. void __mutex_init(struct mutex *lock, constchar *name, struct lock_class_key *key)  
  16. {  
  17.     atomic_set(&lock->count, 1);  
  18.     spin_lock_init(&lock->wait_lock);  
  19.     INIT_LIST_HEAD(&lock->wait_list);  
  20.     mutex_clear_owner(lock);  
  21. #ifdef CONFIG_MUTEX_SPIN_ON_OWNER
  22.     osq_lock_init(&lock->osq);  
  23. #endif
  24.     debug_mutex_init(lock, name, key);  
  25. }  
上面的兩種初始化,效果最後都是一樣。將count初始化為1, 將wait_lock設定為unlock狀態,初始化wait_list連結串列頭。

互斥鎖的DOWN操作

互斥鎖的DOWN操作在linux核心中定義為mutex_lock函式,如下:
  1. /** 
  2.  * mutex_lock - acquire the mutex 
  3.  * @lock: the mutex to be acquired 
  4.  * 
  5.  * Lock the mutex exclusively for this task. If the mutex is not 
  6.  * available right now, it will sleep until it can get it. 
  7.  * 
  8.  * The mutex must later on be released by the same task that 
  9.  * acquired it. Recursive locking is not allowed. The task 
  10.  * may not exit without first unlocking the mutex. Also, kernel 
  11.  * memory where the mutex resides mutex must not be freed with 
  12.  * the mutex still locked. The mutex must first be initialized 
  13.  * (or statically defined) before it can be locked. memset()-ing 
  14.  * the mutex to 0 is not allowed. 
  15.  * 
  16.  * ( The CONFIG_DEBUG_MUTEXES .config option turns on debugging 
  17.  *   checks that will enforce the restrictions and will also do 
  18.  *   deadlock debugging. ) 
  19.  * 
  20.  * This function is similar to (but not equivalent to) down(). 
  21.  */
  22. void __sched mutex_lock(struct mutex *lock)  
  23. {  
  24.     might_sleep();  
  25.     /* 
  26.      * The locking fastpath is the 1->0 transition from 
  27.      * 'unlocked' into 'locked' state. 
  28.      */
  29.     __mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);  
  30.     mutex_set_owner(lock);  
  31. }  

mutex_lock是用來獲得互斥鎖,如果不能立刻獲得互斥鎖,程序將睡眠直到獲得鎖為止。
  1. #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
  2.   void __might_sleep(constchar *file, int line, int preempt_offset);  
  3. /** 
  4.  * might_sleep - annotation for functions that can sleep 
  5.  * 
  6.  * this macro will print a stack trace if it is executed in an atomic 
  7.  * context (spinlock, irq-handler, ...). 
  8.  * 
  9.  * This is a useful debugging help to be able to catch problems early and not 
  10.  * be bitten later when the calling function happens to sleep when it is not 
  11.  * supposed to. 
  12.  */
  13. # define might_sleep() \
  14. 相關推薦

    16.執行緒同步:互斥mutex

    1.案例:兩個執行緒分別對一個變數,都++操作1000次 1.實際的執行結果:number的最終值<2000 2.資料混亂的原因: 多個執行緒操作了共享資源 CPU排程問題 3.解決:執行緒同步 int number=0;

    使用互斥mutex實現訊號量sem

    /* ======================== SYNCHRONISATION ========================= */ /* Init semaphore to 1 or 0 */ void bsem_init(bsem *bsem_p, int valu

    互斥mutex簡單應用

    寫了段小程式碼學習互斥鎖的作用。 互斥鎖的作用:在程式設計中,引入了物件互斥鎖的概念,來保證共享資料操作的完整性。 思路是用2個執行緒對同一個記憶體位置buffer,進行寫和讀,為了防止2個執行緒同時對buffer進行修改,用同一把互斥鎖來限制。 寫操作簡化為把buffer修改為’W’,

    Go基礎系列:互斥Mutex和讀寫RWMutex用法詳述

    sync.Mutex Go中使用sync.Mutex型別實現mutex(排他鎖、互斥鎖)。在原始碼的sync/mutex.go檔案中,有如下定義: // A Mutex is a mutual exclusion lock. // The zero value for a Mutex is an un

    Go語言學習之sync包(臨時物件池Pool、互斥Mutex、等待Cond)(the way to go)

    golang的特點就是語言層面支援併發,並且實現併發非常簡單,只需在需要併發的函式前面新增關鍵字go。 但是如何處理go併發機制中不同goroutine之間的同步與通訊,golang 中提供了sync包來解決相關的問題,當然還有其他的方式比如channel,原子操作atomic等等,這裡先

    互斥mutex的使用方法

    線上程實際執行過程中,我們經常需要多個執行緒保持同步。這時可以用互斥鎖來完成任務;互斥鎖的使用過程中,主要有pthread_mutex_init,pthread_mutex_destory,pthre

    c++互斥mutex使用簡介

    1. 多個執行緒訪問同一資源時,為了保證資料的一致性,最簡單的方式就是使用 mutex(互斥鎖)。 引用 cppreference 的介紹: 1 The mutex class is a synchronization primitive t

    深入理解linux互斥(mutex)

    鎖機制,可以說是linux整個系統的精髓所在,linux核心都是圍繞著同步在運轉。在多程序和多執行緒程式設計中,鎖起著極其重要的作用。我這裡說的是互斥鎖,其實是泛指linux中所有的鎖機制。我在這裡不講如果建立鎖,關於鎖的建立,網上程式碼很多,我在這裡就不多說了。我要談

    互斥mutex

    在訊號量最後的部分說,當count=1的時候可以用訊號量實現互斥。在早期的Linux版本中就是當count=1來實現mutex的。 核心重新定義了一個新的資料結構 struct mutex, 將其稱為互斥鎖或者互斥體。同時對訊號量的DOWN和UP操作針對struct

    [Go] golang互斥mutex

    變量 只有一個 unlock 允許 println main run don UNC 1.互斥鎖用於在代碼上創建一個臨界區,保證同一時間只有一個goroutine可以執行這個臨界區代碼2.Lock()和Unlock()定義臨界區 package main import

    Linux C 程式設計——互斥mutex

    1、多執行緒的問題引入 多執行緒的最大的特點是資源的共享,但是,當多個執行緒同時去操作(同時去改變)一個臨界資源時,會破壞臨界資源。如利用多執行緒同時寫一個檔案: #include <stdio.h> #include <pthread.h

    Golang 讀寫RWMutex 互斥Mutex 原始碼詳解

    前言 Golang中有兩種型別的鎖,Mutex (互斥鎖)和RWMutex(讀寫鎖)對於這兩種鎖的使用這裡就不多說了,本文主要側重於從原始碼的角度分析這兩種鎖的具體實現。   引子問題 我一般喜歡帶著問題去看原始碼。那麼對於讀寫鎖,你是否有這樣的問題,為什麼可以有多個讀鎖?有沒有可能出現有協

    圖解Go裡面的互斥mutex瞭解程式語言核心實現原始碼

    1. 鎖的基礎概念 1.1 CAS與輪詢 1.1.1 cas實現鎖 在鎖的實現中現在越來越多的採用CAS來進行,通過利用處理器的CAS指令來實現對給定變數的值交換來進行鎖的獲取 1.1.2 輪詢鎖 在多執行緒併發的情況下很有可能會有執行緒CAS失敗,通常就會配合for迴圈採用輪詢的方式去嘗試重新獲取鎖

    多圖詳解Go的互斥Mutex

    > 轉載請宣告出處哦~,本篇文章釋出於luozhiyun的部落格:https://www.luozhiyun.com > > 本文使用的go的原始碼時14.4 ## Mutex介紹 Mutex 結構體包含兩個欄位: * 欄位state:表示當前互斥鎖的狀態。 * 欄位 sema:是個訊號量變數,用來控

    不得不知道的golang之sync.Mutex互斥源碼分析

    it is 指點 對象鎖 不能 數值 正常 += lease x11 針對Golang 1.9的sync.Mutex進行分析,與Golang 1.10基本一樣除了將panic改為了throw之外其他的都一樣。源代碼位置:sync\mutex.go。可以看到註釋如下: Mut

    Windows執行緒同步之互斥Mutex

    執行緒同步的方式和機制臨界區、互斥區、事件、訊號量四種方式臨界區(Critical Section)、互斥量(Mutex)、訊號量(Semaphore)、事件(Event)的區別1、臨界區:通過對多執行緒的序列化來訪問公共資源或一段程式碼,速度快,適合控制資料訪問。在任意時刻

    C++易混知識點 6: 如何通過生命週期使用mutex互斥自動加和釋放

    在涉及到多執行緒操作的時候,對於那些靜態變數我們一定要加以保護。我們通常會使用到的是互斥鎖,通過對鎖的獲取和釋放來保證始終只有一個執行緒對關鍵資料進行操作,但這樣帶來的問題也是很直接的: 繁瑣的操作。 1. 首先我們先定義一個互斥鎖的類, class EfMutex {

    WinDbg -- 除錯互斥體(Mutex)死

    一. 演示用例 #include <windows.h> #include <tchar.h> #include <process.h> HANDLE hMutexA = NULL; HANDLE hMutexB =

    自旋(spin lock)與互斥量(mutex)的比較

    from:http://blog.csdn.net/swordmanwk/article/details/6819457 自旋鎖是一種非阻塞鎖,也就是說,如果某執行緒需要獲取自旋鎖,但該鎖已經被其他執行緒佔用時,該執行緒不會被掛起,而是在不斷的消耗CPU的時間,不停的試

    執行緒與互斥(C++11中std::thread和std::mutex的用法)

    執行緒 0 首先是曾經在MultiCMOS專案中用到的: #include <thread> //包含標頭檔案 class IDataProcessUnit { protected: