多執行緒併發鎖分類以及簡單例項

云中锦书来發表於2024-07-21

多執行緒併發鎖

包括自旋鎖、互斥鎖、無鎖

POSIX介面

posix介面提供linux下執行緒操作庫,posix預設生成的執行緒佔用8M空間

  1. pthread_create執行緒建立函式

    pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg) // func是函式指標,是執行緒要呼叫的函式,arg是給呼叫函式傳的引數
    

互斥鎖mutex

執行緒試圖訪問被鎖資源時,執行緒會被阻塞。鎖釋放的時候,會喚醒所有該鎖上阻塞的執行緒。適用於鎖的內容較多的情況,比如佇列

pthread_mutex_t mutex; // 宣告互斥量
pthread_mutex_init(&mutex, NULL); // 預設初始化
ptherad_mutex_lock(&mutex); // 加鎖
ptherad_mutex_lock(&mutex); // 解鎖

自旋鎖spinlock

自旋鎖會一直去嘗試獲取鎖,相當於一個while迴圈獲取。適用於鎖的內容很少比如變數,使用自選鎖,等待代價小於執行緒切換。此時cpu會發生空轉。

pthread_spinlock_t spinlock; // 宣告自旋鎖
pthread_spin_init(&spinlock, PTHERAD_PROCESS_PRIVATE); // 預設初始化
ptherad_spin_lock(&spinlock); // 加鎖
ptherad_spin_lock(&spinlock); // 解鎖

原子操作-無鎖

原子操作解決對應變數需要加鎖的問題,原子操作能夠將變數的指令變為單條CPU指令,這樣就能夠解決執行緒之間不同步的問題。原子操作的速度更快。

int inc(int* value, int add){
    int old;
    // volatile指示編譯器不要對變數進行最佳化
    __asm__ volatile(
        "lock; xaddl %2, %1"
        : "=a" (old)
        : "m" (*value), "a" (add)
        : "cc", "memory"
    );
}

CAS

cas指的是Compare-And-Swap原子操作,能夠保證併發執行緒對共享資料安全訪問和修改。

實現思路

compare用於檢測記憶體地址當前值是否與期望值相等,swap如果期望值等於當前值,則將當前值作為新值。

實現方式

void cas(int *ptr, int expected, int desired) {
    __asm__ volatile (
        "lock; cmpxchg %2, %0\n" // 使用LOCK字首的cmpxchg指令
        : "+m" (*ptr), "+a" (expected) // 運算元約束
        : "r" (desired) // 運算元約束
        : "memory" // 標記記憶體操作
    );
}

相關文章