Swift 線程安全加鎖

在OC中有dispatch_once來實現,在Swift中我們需要自己來根據其原理來實現,類似于增加一個哨兵來標識是否執行過了

原子操作

對于一個資源,在寫入或讀取時,只允許在一個時刻一個角色進行操作,則為原子操作。Swift中 let 聲明的資源,永遠是原子性的。在我們購買火車票時需要保證票數不會在多個線程中同時進行修改,這時就可以使用這種方式來實現。

  • OC實現方式
// 加鎖
@synchronized(<#token#>) {
    <#statements#>
}
  • Swift實現方式
objc_sync_enter(lock)
// TODO:
objc_sync_exit(lock)

購買火車票

// 在Playeground實現
import UIKit
var ticket = 10000

func buyTicket(userName: String) {
    DispatchQueue.global().async {
//        objc_sync_enter(ticket)
        let count = ticket - 1
        ticket = count
//        objc_sync_exit(ticket)
        print("\(userName)買了一張票,剩余票數\(ticket)")
    }
}

for i in 1 ... 200 {
    
    buyTicket(userName: "hc\(i)")
    
}

結果如下:

hc6買了一張票,剩余票數9999
hc3買了一張票,剩余票數9998
hc1買了一張票,剩余票數9999
hc4買了一張票,剩余票數9998
hc2買了一張票,剩余票數9999
hc7買了一張票,剩余票數9998
hc5買了一張票,剩余票數9998
hc8買了一張票,剩余票數9997
hc9買了一張票,剩余票數9997
hc10買了一張票,剩余票數9997
hc11買了一張票,剩余票數9996
hc12買了一張票,剩余票數9996
hc14買了一張票,剩余票數9995
hc13買了一張票,剩余票數9995
hc15買了一張票,剩余票數9994
hc16買了一張票,剩余票數9994
hc17買了一張票,剩余票數9994
hc19買了一張票,剩余票數9994
hc18買了一張票,剩余票數9994
hc20買了一張票,剩余票數9993
hc22買了一張票,剩余票數9993
hc21買了一張票,剩余票數9993
hc23買了一張票,剩余票數9993
hc24買了一張票,剩余票數9992
hc25買了一張票,剩余票數9992
hc26買了一張票,剩余票數9991
hc27買了一張票,剩余票數9991
hc28買了一張票,剩余票數9991
hc29買了一張票,剩余票數9991
···

將加鎖部分objc_sync_enter(ticket),objc_sync_exit(ticket)打開后結果如下:

hc1買了一張票,剩余票數9999
hc9買了一張票,剩余票數9998
hc12買了一張票,剩余票數9997
hc17買了一張票,剩余票數9996
hc20買了一張票,剩余票數9995
hc21買了一張票,剩余票數9994
hc22買了一張票,剩余票數9993
hc23買了一張票,剩余票數9992
hc24買了一張票,剩余票數9991
hc25買了一張票,剩余票數9990
hc26買了一張票,剩余票數9989
hc27買了一張票,剩余票數9988
hc28買了一張票,剩余票數9987
hc33買了一張票,剩余票數9986
hc38買了一張票,剩余票數9985
hc42買了一張票,剩余票數9984
hc47買了一張票,剩余票數9983
hc51買了一張票,剩余票數9982
hc55買了一張票,剩余票數9981
···

dispatch_once在Swift中的實現

extension DispatchQueue {
    fileprivate static var _onceToken = [String]()
    
    static func once(token: String, block: () -> Void) {
        objc_sync_enter(self)
        
        defer {
            objc_sync_exit(self)
        }
        
        if _onceToken.contains(token) {
            return
        }
        _onceToken.append(token)
        block()
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容