- 線程的同步與互斥
2019-12-07:
(POSIX中2種線程同步機制)
因線程共享進程的資源、地址空間,所以對該類資源進行操作時,一定要考慮線程間資源訪問同步和互斥的問題;(2種同步機制也可互相通過調用對方來實現)
互斥鎖:更適合用於同時可用的資源 是唯一的情況;
信號量:更適合用於同時可用的資源 爲多個的情況;
- 互斥鎖:針對線程
互斥鎖是用一種簡單的加鎖方法來控制對共享資源的原子操作,一定程度上可以看做是全局變量。
互斥鎖只有2中狀態,即上鎖和解鎖(同一時刻只允許1個線程掌握某個互斥鎖,擁有上鎖狀態的線程能夠對共享資源進行操作;若其他線程希望上鎖,只能先掛起直到上鎖的線程釋放互斥鎖爲止)。
互斥鎖保證讓每個線程對共享資源按順序進行原子操作。
互斥鎖機制的基本函數:#include <pthread.h>, returen 0表示成功
初始化:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const
pthread_mutexattr_t *restrict attr);
// mutex互斥鎖; attr互斥鎖屬性:快速(NULL默認)、遞歸、檢錯
上鎖:
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);
初始化互斥鎖時,有快速(默認阻塞等待)、遞歸、檢錯3種類型互斥鎖,其區別在於其他未佔用的互斥鎖的線程在希望得到互斥鎖時是否需要阻塞等待。
【互斥鎖實驗:】
使得原來獨立無序的線程能夠按順序執行,先到先得鎖,則先使用資源
- 信號量:針對進程或線程
信號量,即操作系統中的PV原子操作,主要用戶進程或線程間的同步與互斥;其本質上是一個非負的整數計數器;被用來控制對共享資源的訪問。
PV原子操作:是對整數計數器信號量sem的操作,P減V加;進程或線程根據信號量sem的值來判斷是否對公共資源具有訪問權限。(當sem>=0時,具有對公共資源的訪問權限,否則沒有,阻塞等待直到sem的值>=0爲止)
PV原子操作使用場景:用戶對進程或線程間同步或者互斥操作;
用於互斥操作:幾個進程或線程只設置1個信號量sem;
用於同步操作:設置多個信號量,並安排不同的初始值來實現他們之間的順序執行。
POSIX無名信號量常見函數:#include <semaphore.h>
初始化:
int sem_init(sem_t *sem, int pshared, unsigned int value);
// sem信號量指針; pshared初始爲0,目前不支持進程間共享信號量; value信號量初始值
P操作:
int sem_wait(sem_t *sem); // sem<0時,阻塞等待
int sem_trywait(sem_t *sem); // sem<0時,立即返回錯誤值
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
sem_timedwait() is the same as sem_wait(), except that abs_timeout specifies a limit on the amount of time that the call should block if the decrement cannot be immediately performed. The abs_timeout argument points to a structure that specifies an absolute timeout in seconds and nanoseconds since the Epoch(00:00:00, 1 January 1970). This structure is defined as follows:
struct timespec {
time_t tv_sec; /* Seconds */
long tv_nsec; /* Nanoseconds [0 .. 999999999] */
};
V操作:
int sem_post(sem_t *sem);
// 將sem值+1,同時發出信號來喚醒等待的進程
獲取信號量的值:
int sem_getvalue(sem_t *sem, int *sval);
刪除信號量:
Int sem_destroy(sem_t *sem);
【信號量實驗】
使用信號量同步機制實現多線程之間的順序訪問
【總結】
使用信號量、互斥鎖實現多線程之間的同步機制,兩者那個更爲合理?區別與聯繫是?
信號量:可以認爲的控制多個線程之間的執行順序
互斥鎖:多個線程順序執行:互斥鎖是先到先得,誰先拿到互斥鎖誰先執行。