异步读写造成数组越界
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| let count = 100000 var array = Array(0 ... count)
func getLast() -> Int { // ⚠️⚠️ 这里加了判断看似安全,但在异步操作时 判断 array.count > 0 的同时可能就有一个异步的操作改变了数组 if array.count > 0 { return array[array.count - 1] } return -1 }
func removeLast() { array.removeLast() }
DispatchQueue.global().async { for _ in 0 ... count { removeLast() } }
DispatchQueue.global().async { for _ in 0 ... count { print(getLast()) } }
|
使用 barrier
会保证在同一个队列中 .barrier 执行完之后才会去做其他线程操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| let count = 100000 var array = Array(0 ... count) let arrayQueue = DispatchQueue(label: "arrayQueue", attributes: DispatchQueue.Attributes.concurrent)
func getLast() -> Int { arrayQueue.sync { () -> Int in if array.count > 0 { return array[array.count - 1] } return -1 } }
func removeLast() { //⚠️⚠️ 这里使用 barrier let workItem = DispatchWorkItem(qos: DispatchQoS.default, flags: DispatchWorkItemFlags.barrier) { array.removeLast() } arrayQueue.async(execute: workItem) }
DispatchQueue.global().async { for _ in 0 ... count { removeLast() } }
DispatchQueue.global().async { for _ in 0 ... count { print(getLast()) } }
|