美文网首页
使用队列实现线程同步

使用队列实现线程同步

作者: 来金德瑞 | 来源:发表于2021-03-16 11:09 被阅读0次
    • 多个线程访问同一块资源时候,容易引发数据错乱与数据安全问题
    • 使用GCD中的串行队列,是实现线程同步的一个常规方案,并且效率也不低

    资源竞争的案例

        // 起初有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)")
        }
    

    竞争导致的后果

    取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
        
        // 创建一个串行队列
        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)}

    相关文章

      网友评论

          本文标题:使用队列实现线程同步

          本文链接:https://www.haomeiwen.com/subject/kxicxltx.html