同步
同一個進程中的多個線程共享所在進程的內存資源,當多個線程在同一時刻同時訪問同一種共享資源時,需要相互協調,以避免出現數據的不一致和覆蓋等問題,線程之間的協調和通信的就叫做線程的同步問題, 線程同步的思路: 讓多個線程依次訪問共享資源,而不是並行
互斥VS同步
- 互斥:是指某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。
- 同步:是指在互斥的基礎上(大多數情況),通過其它機制實現訪問者對資源的有序訪問。在大多數情況下,同步已經實現了互斥,特別是所有寫入資源的情況必定是互斥的。少數情況是指可以允許多個訪問者同時訪問資源
互斥量Mutex:
- 本質上說就是一把鎖,提供對資源的獨占訪問,所以Mutex主要的作用是用於互斥。互斥量使同時只能有一個進程訪問數據,可以看做一種的0/1信號量
- Mutex對象的值只有0和1。分別代表了Mutex的鎖定狀態和空閒狀態:
- 鎖定狀態:當前對象被鎖定,用戶進程/線程如果試圖Lock臨界資源,則進入等待;
- 空閒狀態:當前對象為空閒,用戶進程/線程可以Lock臨界資源,之後Mutex值減1變為0。
- Mutex被創建時可以有初始值,表示Mutex被創建後,是鎖定狀態還是空閒狀態。
- 在同一個線程中,為了防止死鎖,系統不允許連續兩次對Mutex加鎖(系統一般會在第二次調用立刻返回)。也就是說,加鎖和解鎖這兩個對應的操作,需要在同一個線程中完成。
互斥量模型
- 定義互斥鎖: pthread_t mutex
- 初始化鎖: pthread_mutex_init()
- 加鎖: pthread_mutex_lock()/pthread_mutex_trylock()
- 解鎖: pthread_mutex_unlock()
- 銷毀: pthread_mutex_destroy()
//成功返回0,失敗返回error number
#include <pthread.h>
int pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
int pthread_mutex_lock (pthread_mutex_t *mutex);
int pthread_mutex_trylock (pthread_mutex_t *mutex);
int pthread_mutex_unlock (pthread_mutex_t *mutex);
int pthread_mutex_destroy (pthread_mutex_t *mutex);
死鎖(deadlock)
主要發生在有多個依賴鎖存在時, 會在一個線程試圖以與另一個線程相反順序鎖住互斥量時發生:
A試圖按照AB的方向使用共享資源,B試圖按照BA的方向使用共享資源,不巧的是,此時鎖定A資源等待B資源被釋放, 也在鎖定B資源等待A資源被釋放, 二者將要使用的資源都被對方鎖著, 形成了死鎖。
為避免死鎖, 有幾個不成文的基本原則:
- 對共享資源操作前一定要獲得鎖。
- 完成操作以後一定要釋放鎖。
- 盡量短時間地占用鎖。
- 如果有多鎖, 如獲得順序是ABC連環扣, 釋放順序也應該是ABC。
- 線程錯誤返回時應該釋放它所獲得的鎖。