線程同步之os_unfair_lock

這是併發控制方案的系列文章,介紹了各種鎖的使用及優缺點。

  1. 自旋鎖
  2. os_unfair_lock
  3. 互斥鎖
  4. 遞歸鎖
  5. 條件鎖
  6. 讀寫鎖
  7. @synchronized

OSSpinLock、os_unfair_lock、pthread_mutex_t、pthread_cond_t、pthread_rwlock_t 是值類型,不是引用類型。這意味着使用 = 會進行復制,使用複製的可能導致閃退。pthread 函數認爲其一直處於初始化的內存地址,將其移動到其他內存地址會產生問題。使用copy的OSSpinLock不會崩潰,但會得到一個全新的鎖。

如果你對線程、進程、串行、併發、並行、鎖等概念還不瞭解,建議先查看以下文章:

os_unfair_lock是一種底層鎖,用於取代OSSpinLock,嘗試獲取已加鎖的線程無需忙等,解鎖時由內核喚醒。和OSSpinLock一樣,os_unfair_lock也沒有加強公平性和順序。例如,釋放鎖的線程可能立即再次加鎖,而之前等待鎖的線程喚醒後沒有機會嘗試加鎖。這樣有利於提高性能,但也造成了飢餓(starvation)。

Starvation 指貪婪線程佔用共享資源太長時間,其他線程無法訪問共享資源、無法取得進展。例如,某對象的同步方法佔用時間過長,並且頻繁調用,其他線程嘗試調用該方法時會被堵塞,處於 starvation。

存儲在鎖中的值應被認爲是不透明的,並且在實現中定義。其包含線程信息,系統可用於解決優先級反轉問題。

1. 初始化os_unfair_lock

os_unfair_lock結構體包含 unfair lock 數據。

初始化方法如下:

    private var moneyLock: os_unfair_lock = os_unfair_lock_s()
    private var ticketLock: os_unfair_lock = os_unfair_lock_s()

如果在 Objective-C 中使用os_unfair_lock,則應導入#import <os/lock.h>頭文件。

2. 加鎖os_unfair_lock_lock() os_unfair_lock_trylock()

由於鎖的實現依賴鎖值和擁有鎖進程的地址,因此線程、進程不能通過共享、映射內存地址獲取os_unfair_lock

加鎖方法如下:

        os_unfair_lock_lock(&moneyLock)

如果鎖已經加鎖,os_unfair_lock_lock()會休眠,解鎖後由內核喚醒。os_unfair_lock_trylock()遇到已經加鎖的鎖,會直接返回 false。不要在循環中調用os_unfair_lock_trylock()函數,os_unfair_lock_lock()函數已經實現了循環功能。

3. 解鎖os_unfair_lock_unlock()

必須在加鎖的線程調用os_unfair_lock_unlock()解鎖,從其他線程解鎖會產生運行時錯誤。

解鎖方法如下:

        os_unfair_lock_unlock(&moneyLock)

完整的代碼如下:

class OSUnfairLockDemo: BaseDemo {
    private var moneyLock: os_unfair_lock = os_unfair_lock_s()
    private var ticketLock: os_unfair_lock = os_unfair_lock_s()
    
    override func drawMoney() {
        os_unfair_lock_lock(&moneyLock)
        
        super.drawMoney()
        
        os_unfair_lock_unlock(&moneyLock)
    }
    
    override func saveMoney() {
        os_unfair_lock_lock(&moneyLock)
        
        super.saveMoney()
        
        os_unfair_lock_unlock(&moneyLock)
    }
    
    override func saleTicket() {
        os_unfair_lock_lock(&ticketLock)
        
        super.saleTicket()
        
        os_unfair_lock_unlock(&ticketLock)
    }
}

通常,應優先選擇使用高級同步工具。如 pthread、dispatch 等提供的同步方案。

Demo名稱:Synchronization
源碼地址:https://github.com/pro648/BasicDemos-iOS/tree/master/Synchronization

上一篇:線程同步之自旋鎖

下一篇:線程同步之互斥鎖

參考資料:

  1. Starvation and Livelock
  2. Synchronization

歡迎更多指正:https://github.com/pro648/tips

本文地址:https://github.com/pro648/tips/blob/master/sources/%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%AD%A5%E4%B9%8Bos_unfair_lock.md

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章