Working in Thread Safe on iOS

為什麼要保證Thread Safe?

Multiple threads 同時間存取data,會導致race condition或是程式crash

例子(以Swift的Array為例):

1) Race condition

每次執行後,array最終的內容都不同。

2) Crash

同時間存取同個array,有機率導致crash,如下圖所示。

在Swift中避免Not Thread Safe方式:

  1. 使用Serial Queue
  2. 使用Barrier flag

使用Serial Queue

class ThreadSafeArray<T> {
    var array = [T]()
    let serialQueue = DispatchQueue(label: "CustomQueue")
    
    var last: T? {
        var result: T?
        serialQueue.sync {
            result = array.last
        }
        return result
    }

    func append(_ item: T) {
        serialQueue.async {
            self.array.append(item)
        }
    }
}

Note: Read理論上能要支援concurrent access,但用serialQueue的實作仍然會讓Read是循序執行。

使用Barrier flag

class ThreadSafeArray2<T> {
    var array = [T]()
    let concurrentQueue = DispatchQueue(label: "CustomQueue", attributes: .concurrent)
    
    var last: T? {
        var result: T?
        concurrentQueue.sync {
            result = array.last
        }
        return result
    }
    
    func append(_ item: T) {
        concurrentQueue.async(flags: .barrier) {
            self.array.append(item)
        }
    }
}

Note: 因為使用concurrentQueue的實作,所以Read在這裡能支援concurrent access。

Ref: https://uynguyen.github.io/2018/06/05/Working-In-Thread-Safe-on-iOS/