使用隊列實現(xiàn)線程同步

  • 多個線程訪問同一塊資源時候,容易引發(fā)數(shù)據(jù)錯亂與數(shù)據(jù)安全問題
  • 使用GCD中的串行隊列,是實現(xiàn)線程同步的一個常規(guī)方案,并且效率也不低

資源競爭的案例

    // 起初有50塊錢
    private var money = 50
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        /// 存錢取錢測試代碼
        moneyTest()
    }
    
    
    /// 多線程競爭money這個資源
    func moneyTest() {
        DispatchQueue.global().async {
            for _ in 0...10 {
                self.saveMoney()
            }
        }
        
        DispatchQueue.global().async {
            for _ in 0...10 {
                self.drawMoney()
            }
        }
    }

    
    /// 存錢
    private func saveMoney() {
        var oldMoney = self.money
        sleep(1)
        oldMoney = oldMoney + 50
        self.money = oldMoney
        print("存50,還剩余\(oldMoney) - \(Thread.current)")
    }
    
    /// 取錢
    private func drawMoney() {
        var oldMoney = self.money
        sleep(1)
        oldMoney = oldMoney - 20
        self.money = oldMoney
        print("取20,還剩余\(oldMoney) - \(Thread.current)")
    }

競爭導(dǎo)致的后果

取20,還剩余0 - <NSThread: 0x60000300b400>{number = 6, name = (null)}
存50,還剩余100 - <NSThread: 0x6000030461c0>{number = 7, name = (null)}
取20,還剩余50 - <NSThread: 0x60000300b400>{number = 6, name = (null)}
存50,還剩余150 - <NSThread: 0x6000030461c0>{number = 7, name = (null)}
取20,還剩余0 - <NSThread: 0x60000300b400>{number = 6, name = (null)}
存50,還剩余200 - <NSThread: 0x6000030461c0>{number = 7, name = (null)}
取20,還剩余-50 - <NSThread: 0x60000300b400>{number = 6, name = (null)}
存50,還剩余250 - <NSThread: 0x6000030461c0>{number = 7, name = (null)}
取20,還剩余-100 - <NSThread: 0x60000300b400>{number = 6, name = (null)}
存50,還剩余300 - <NSThread: 0x6000030461c0>{number = 7, name = (null)}
取20,還剩余-150 - <NSThread: 0x60000300b400>{number = 6, name = (null)}
存50,還剩余350 - <NSThread: 0x6000030461c0>{number = 7, name = (null)}
取20,還剩余-200 - <NSThread: 0x60000300b400>{number = 6, name = (null)}
存50,還剩余400 - <NSThread: 0x6000030461c0>{number = 7, name = (null)}
取20,還剩余-250 - <NSThread: 0x60000300b400>{number = 6, name = (null)}
存50,還剩余450 - <NSThread: 0x6000030461c0>{number = 7, name = (null)}
取20,還剩余-300 - <NSThread: 0x60000300b400>{number = 6, name = (null)}
存50,還剩余500 - <NSThread: 0x6000030461c0>{number = 7, name = (null)}
取20,還剩余-350 - <NSThread: 0x60000300b400>{number = 6, name = (null)}
存50,還剩余550 - <NSThread: 0x6000030461c0>{number = 7, name = (null)}
取20,還剩余-400 - <NSThread: 0x60000300b400>{number = 6, name = (null)}
存50,還剩余600 - <NSThread: 0x6000030461c0>{number = 7, name = (null)}

如何解決該問題

    // 起初有50塊錢
    private var money = 50
    
    // 創(chuàng)建一個串行隊列
    private let queue = DispatchQueue(label: "com.nsl.serialQueue")
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        /// 存錢取錢測試代碼
        moneyTest()
    }
    
    /// 多線程競爭money這個資源
    func moneyTest() {
        DispatchQueue.global().async {
            for _ in 0...10 {
                self.saveMoney()
            }
        }
        
        DispatchQueue.global().async {
            for _ in 0...10 {
                self.drawMoney()
            }
        }
    }

    /// 存錢
    private func saveMoney() {
        // 串行 + 同步
        self.queue.sync {
            var oldMoney = self.money
            sleep(1)
            oldMoney = oldMoney + 50
            self.money = oldMoney
            print("存50,還剩余\(oldMoney) - \(Thread.current)")
        }
  
    }
    
    /// 取錢
    private func drawMoney() {
        // 串行 + 同步
        self.queue.sync {
            var oldMoney = self.money
            sleep(1)
            oldMoney = oldMoney - 20
            self.money = oldMoney
            print("取20,還剩余\(oldMoney) - \(Thread.current)")
        }
    }

解決問題后的輸出

取20,還剩余30 - <NSThread: 0x600001222740>{number = 6, name = (null)}
存50,還剩余80 - <NSThread: 0x60000122e780>{number = 7, name = (null)}
取20,還剩余60 - <NSThread: 0x600001222740>{number = 6, name = (null)}
存50,還剩余110 - <NSThread: 0x60000122e780>{number = 7, name = (null)}
取20,還剩余90 - <NSThread: 0x600001222740>{number = 6, name = (null)}
存50,還剩余140 - <NSThread: 0x60000122e780>{number = 7, name = (null)}
取20,還剩余120 - <NSThread: 0x600001222740>{number = 6, name = (null)}
存50,還剩余170 - <NSThread: 0x60000122e780>{number = 7, name = (null)}
取20,還剩余150 - <NSThread: 0x600001222740>{number = 6, name = (null)}
存50,還剩余200 - <NSThread: 0x60000122e780>{number = 7, name = (null)}
取20,還剩余180 - <NSThread: 0x600001222740>{number = 6, name = (null)}
存50,還剩余230 - <NSThread: 0x60000122e780>{number = 7, name = (null)}
取20,還剩余210 - <NSThread: 0x600001222740>{number = 6, name = (null)}
存50,還剩余260 - <NSThread: 0x60000122e780>{number = 7, name = (null)}
取20,還剩余240 - <NSThread: 0x600001222740>{number = 6, name = (null)}
存50,還剩余290 - <NSThread: 0x60000122e780>{number = 7, name = (null)}
取20,還剩余270 - <NSThread: 0x600001222740>{number = 6, name = (null)}
存50,還剩余320 - <NSThread: 0x60000122e780>{number = 7, name = (null)}
取20,還剩余300 - <NSThread: 0x600001222740>{number = 6, name = (null)}
存50,還剩余350 - <NSThread: 0x60000122e780>{number = 7, name = (null)}
取20,還剩余330 - <NSThread: 0x600001222740>{number = 6, name = (null)}
存50,還剩余380 - <NSThread: 0x60000122e780>{number = 7, name = (null)}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容