線程同步
????????協同步調,對公共區域數據按序訪問。防止數據混亂,產生與時間有關的錯誤。
數據混亂的原因
資源共享(獨享資源則不會)
調度隨機(意味著數據訪問會出現競爭)
線程間缺乏必要同步機制
鎖的使用
????????建議鎖!對公共數據進行保護。所有線程【應該】在訪問公共數據前先拿鎖再訪問。但,鎖本身不具備強制性。
主要應用函數:
??? pthread_mutex_init?????? 函數:創建鎖
??? pthread_mutex_destory??? 函數:初始化
??? pthread_mutex_lock?????? 函數:加鎖
??? pthread_mutex_trylock??? 函數:
??? pthread_mutex_unlock???? 函數:解鎖
以上5個函數的返回值都是:成功返回0,失敗返回錯誤號
、、、、、、、、、、、
pthread_mutex_t 類型,其本質是一個結構體。為簡化理解,應用時可忽略其實現細節,簡單當成整數看待
pthread_mutex_t mutex;變量mutex只有兩種取值:0,1
、、、、、、、
使用mutex(互斥量、互斥鎖)一般步驟:
??? pthread_mutex_t 類型。
??? 1. pthread_mutex_t lock;? 創建鎖
??? 2? pthread_mutex_init; 初始化????? 1
??? 3. pthread_mutex_lock;加鎖????? 1-- --> 0
??? 4. 訪問共享數據(stdout)???
??? 5. pthrad_mutext_unlock();解鎖???? 0++ --> 1
??? 6. pthead_mutex_destroy;銷毀鎖
、、、、、、、、、、、
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr)
這里的restrict關鍵字,表示指針指向的內容只能通過這個指針進行修改
restrict關鍵字:
??? 用來限定指針變量。被該關鍵字限定的指針變量所指向的內存操作,必須由本指針完成。
初始化互斥量:
?????? pthread_mutex_t mutex;
?????? 1. pthread_mutex_init(&mutex, NULL);?? ?????? ??? 動態初始化。
?????? 2. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;? 靜態初始化。
例子:借助互斥鎖管理共享數據實現同步
未加鎖
加鎖
互斥鎖使用技巧
注意事項:
?????? 盡量保證鎖的粒度, 越小越好。(訪問共享數據前,加鎖。訪問結束【立即】解鎖。)
?????? 互斥鎖,本質是結構體。 我們可以看成整數。 初值為 1。(pthread_mutex_init() 函數調用成功。)
?????? 加鎖: --操作, 阻塞線程。
?????? 解鎖: ++操作, 喚醒阻塞在鎖上的線程。
?????? try鎖:嘗試加鎖,成功--。失敗,返回。同時設置錯誤號 EBUSY
死鎖
是使用鎖不恰當導致的現象:
?????? 1. 對一個鎖反復lock。
?????? 2. 兩個線程,各自持有一把鎖,請求另一把。
第一種情況,反復加鎖;
第二種情況,1先拿A鎖,2先拿B鎖,1又要拿B,2又要拿A,就都在這阻塞等待。
讀寫鎖
特性:
- 讀寫鎖是“寫模式加鎖”時, 解鎖前,所有對該鎖加鎖的線程都會被阻塞。
- 讀寫鎖是“讀模式加鎖”時, 如果線程以讀模式對其加鎖會成功;如果線程以寫模式加鎖會阻塞。
- 讀寫鎖是“讀模式加鎖”時, 既有試圖以寫模式加鎖的線程,也有試圖以讀模式加鎖的線程。那么讀寫鎖會阻塞隨后的讀模式鎖請求。優先滿足寫模式鎖。讀鎖、寫鎖并行阻塞,寫鎖優先級高
??????? 讀寫鎖也叫共享-獨占鎖。當讀寫鎖以讀模式鎖住時,它是以共享模式鎖住的;當它以寫模式鎖住時,它是以獨占模式鎖住的。寫獨占、讀共享。
??????? 讀寫鎖非常適合于對數據結構讀的次數遠大于寫的情況。
、、、、、、、、、、、、
??? 鎖只有一把。以讀方式給數據加鎖——讀鎖。以寫方式給數據加鎖——寫鎖。
??? 讀共享,寫獨占。
??? 寫鎖優先級高。(兩個寫,一個讀,等兩個寫結束再讀)
??? 相較于互斥量而言,當讀線程多的時候,提高訪問效率
??? pthread_rwlock_t? rwlock;
??? pthread_rwlock_init(&rwlock, NULL);
??? pthread_rwlock_rdlock(&rwlock);??? try
??? pthread_rwlock_wrlock(&rwlock);??? try
??? pthread_rwlock_unlock(&rwlock);
??? pthread_rwlock_destroy(&rwlock);
以上函數都是成功返回0,失敗返回錯誤號。
pthread_rwlock_t 類型??? 用于定義一個讀寫鎖變量
pthread_rwlock_t? rwlock
例子
3個線程不定時?"寫"?全局資源,5個線程不定時?"讀"?同一全局資源