目錄
線程互斥
鎖
初始化?
銷毀
加鎖
解鎖?
線程同步
條件變量
初始化
銷毀
等待條件滿足
喚醒等待
pthread_cond_signal
pthread_cond_broadcast
生產者消費者模型
3種關系
2種角色
1個交易場所?
POSIX信號量
初始化
銷毀
等待
發布
線程互斥
互斥相關概念
臨界資源:多線程執行流共享的資源就叫做臨界資源。?
臨界區:每個線程內部,訪問臨界資源的代碼,就叫做臨界區。
互斥:任何時刻,互斥保證有且只有一個執行流進入臨界區,訪問臨界資源,通常對臨界資源起保護作用。
原子性:不會被任何調度機制打斷的操作,該操作只有兩態,要么完成,要么未完成。
多線程并發操作一些共享變量會有一些問題
例如變量++,--的操作就不能多線程并發訪問
++,--的操作在匯編中需要分為3步
1.將變量從內存加載到寄存器中
2.更新寄存器里面的值,執行+1(-1)操作
3.將新值從寄存器寫回會變量的內存地址中
因為寄存器用的都是同一個,在并發訪問時就會出現問題
要解決以上問題,需要做到三點:
1.代碼必須要有互斥行為:當代碼進入臨界區執行時,不允許其他線程進入該臨界區。?
2.如果多個線程同時要求執行臨界區的代碼,并且臨界區沒有線程在執行,那么只能允許一個線程進入該臨界區。
3.如果線程不在臨界區中執行,那么該線程不能阻止其他線程進入臨界區。
想要做到這三點,我們可以使用一把鎖。Linux上提供的這把鎖叫互斥量?
鎖
pthread_mutex_t?
這是一個互斥鎖的類型,定義在POSIX線程庫中。
互斥鎖用于保護共享資源的訪問,確保在多線程環境中,同一時間只有一個線程可以訪問該資源,從而避免數據競爭和不一致的問題。
我們可以用這個類型來定義一個鎖變量,并初始化它
初始化?
方法1:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER?
PTHREAD_MUTEX_INITIALIZER這是一個宏,用于初始化靜態分配的互斥鎖
方法2:
#include <pthread.h>int pthread_mutex_init(pthread_mutex_t *mutex,
const pthread_mutexattr_t *mutexattr);
mutex:指向要初始化的互斥鎖對象的指針
mutexattr:指向互斥鎖屬性對象的指針。如果為NULL,則使用默認屬性(一般情況使用NULL即可)
返回值:
成功:返回0?
失敗:返回錯誤碼
銷毀
鎖也需要像malloc,new出來的動態內存一樣需要我們手動釋放,但并不是所有情況都需要手動釋放的
當使用PTHREAD_MUTEX_INITIALIZER初始化的互斥量不需要銷毀
#include <pthread.h>int pthread_mutex_destroy(pthread_mutex_t *mutex);
mutex:指向要銷毀的互斥鎖對象的指針
返回值:
成功:返回0?
失敗:返回錯誤碼
加鎖
我們可以對一段代碼區進行加鎖,這樣就只能有單執行流訪問一段代碼了
#include <pthread.h>int pthread_mutex_lock(pthread_mutex_t *mutex);
pthread_mutex_lock用于鎖定一個互斥鎖
mutex:指向要鎖定的互斥鎖對象的指針
返回值:
成功:返回0?
失敗:返回錯誤碼
解鎖?
有加鎖當然也會有解鎖,加鎖和解鎖之間的區域就是我們擁有鎖的區域
#include <pthread.h>int pthread_mutex_unlock(pthread_mutex_t *mutex);
pthread_mutex_unlock用于解鎖一個互斥鎖
mutex:指向要解鎖的互斥鎖對象的指針
返回值:
成功:返回0?
失敗:返回錯誤碼
線程同步
條件變量
條件變量是一種在多線程編程中用于線程同步的機制,它允許線程在某些條件不滿足時進入等待狀態,直到條件滿足時才被喚醒繼續執行。?
初始化
初始化一個條件變量。
int pthread_cond_init(pthread_cond_t *cond
, const pthread_condattr_t *cond_attr);
cond:指向條件變量的指針,需要初始化的條件變量。
cond_attr:?指向條件變量屬性的指針。如果為NULL,則使用默認屬性。
返回值:
成功:返回0?
失敗:返回錯誤碼
銷毀
銷毀一個條件變量,釋放相關資源。?
int pthread_cond_destroy(pthread_cond_t *cond);
?cond:指向條件變量的指針,需要銷毀的條件變量。
返回值:
成功:返回0?
失敗:返回錯誤碼
等待條件滿足
使線程進入等待狀態,直到條件變量被通知。?
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
cond:指向條件變量的指針。
mutex:指向互斥鎖的指針,該互斥鎖必須已經被當前線程鎖定。
當調用pthread_cond_wait的時候,線程會釋放mutex,并進入等待狀態
當條件變量被通知時,線程會被喚醒,并重新嘗試獲取mutex
喚醒等待
pthread_cond_signal
通知一個等待條件變量的線程。
int pthread_cond_signal(pthread_cond_t *cond);
cond:指向條件變量的指針。
返回值:
成功:返回0?
失敗:返回錯誤碼
pthread_cond_broadcast
通知所有等待條件變量的線程。
int pthread_cond_broadcast(pthread_cond_t *cond);
cond:指向條件變量的指針。
返回值:
成功:返回0?
失敗:返回錯誤碼
生產者消費者模型
3種關系
生產者之間:競爭關系,互斥關系
消費者之間:競爭關系,互斥關系
生產者和消費者之間:競爭關系,互斥關系,同步關系
2種角色
生產者角色和消費者角色
1個交易場所?
以特定結構構成的內存空間
POSIX信號量
初始化
初始化一個信號量。
#include <semaphore.h>int sem_init(sem_t *sem, int pshared, unsigned int value);
sem:指向信號量的指針。
pshared:指定信號量是否可以在不同進程之間共享。為0:信號量僅在當前進程內的線程之間共享。非0:信號量可以在不同進程之間共享(需要映射到共享內存)
value:信號量的初始值。
返回值:
成功:返回0?
失敗:返回錯誤碼
銷毀
銷毀一個信號量,釋放相關資源。?
#include <semaphore.h>int sem_destroy(sem_t *sem);
sem:指向信號量的指針。
返回值:
成功:返回0?
失敗:返回錯誤碼
等待
使線程進入等待狀態,直到信號量的值大于零,然后將信號量的值減一。
#include <semaphore.h>int sem_wait(sem_t *sem);
sem:指向信號量的指針。
返回值:
成功:返回0?
失敗:返回錯誤碼
發布
將信號量的值加一,通知等待信號量的線程。
#include <semaphore.h>int sem_post(sem_t *sem);
sem:指向信號量的指針。
返回值:
成功:返回0?
失敗:返回錯誤碼
完