- 多個線程訪問同一塊資源時候垄潮,容易引發(fā)數據錯亂與數據安全問題
- 使用GCD中的串行隊列梧奢,是實現線程同步的一個常規(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)")
}
競爭導致的后果
取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)}