Create thread safe array in Swift Create thread safe array in Swift multithreading multithreading

Create thread safe array in Swift


Update for Swift

The recommended pattern for thread-safe access is using dispatch barrier:

let queue = DispatchQueue(label: "thread-safe-obj", attributes: .concurrent)// writequeue.async(flags: .barrier) {    // perform writes on data}// readvar value: ValueType!queue.sync {    // perform read and assign value}return value


Kirsteins's answer is correct, but for convenience, I've updated that answer with Amol Chaudhari and Rob's suggestions for using a concurrent queue with async barrier to allow concurrent reads but block on writes.

I've also wrapped some other array functions that were useful to me.

public class SynchronizedArray<T> {private var array: [T] = []private let accessQueue = dispatch_queue_create("SynchronizedArrayAccess", DISPATCH_QUEUE_CONCURRENT)public func append(newElement: T) {    dispatch_barrier_async(self.accessQueue) {        self.array.append(newElement)    }}public func removeAtIndex(index: Int) {    dispatch_barrier_async(self.accessQueue) {        self.array.removeAtIndex(index)    }}public var count: Int {    var count = 0    dispatch_sync(self.accessQueue) {        count = self.array.count    }    return count}public func first() -> T? {    var element: T?    dispatch_sync(self.accessQueue) {        if !self.array.isEmpty {            element = self.array[0]        }    }    return element}public subscript(index: Int) -> T {    set {        dispatch_barrier_async(self.accessQueue) {            self.array[index] = newValue        }    }    get {        var element: T!        dispatch_sync(self.accessQueue) {            element = self.array[index]        }        return element    }}}

UPDATEThis is the same code, updated for Swift3.

public class SynchronizedArray<T> {private var array: [T] = []private let accessQueue = DispatchQueue(label: "SynchronizedArrayAccess", attributes: .concurrent)public func append(newElement: T) {    self.accessQueue.async(flags:.barrier) {        self.array.append(newElement)    }}public func removeAtIndex(index: Int) {    self.accessQueue.async(flags:.barrier) {        self.array.remove(at: index)    }}public var count: Int {    var count = 0    self.accessQueue.sync {        count = self.array.count    }    return count}public func first() -> T? {    var element: T?    self.accessQueue.sync {        if !self.array.isEmpty {            element = self.array[0]        }    }    return element}public subscript(index: Int) -> T {    set {        self.accessQueue.async(flags:.barrier) {            self.array[index] = newValue        }    }    get {        var element: T!        self.accessQueue.sync {            element = self.array[index]        }        return element    }}}


My approach to this problem was using serial dispatch queue, to synchronise access to boxed array. It will block the thread when you try to get the value at index and queue is really busy, but that's the problem with locks as well.

public class SynchronizedArray<T> {    private var array: [T] = []    private let accessQueue = dispatch_queue_create("SynchronizedArrayAccess", DISPATCH_QUEUE_SERIAL)    public func append(newElement: T) {        dispatch_async(self.accessQueue) {            self.array.append(newElement)        }    }    public subscript(index: Int) -> T {        set {            dispatch_async(self.accessQueue) {                self.array[index] = newValue            }        }        get {            var element: T!            dispatch_sync(self.accessQueue) {                element = self.array[index]            }            return element        }    }}var a = SynchronizedArray<Int>()a.append(1)a.append(2)a.append(3)// can be empty as this is non-thread safe accessprintln(a.array)// thread-safe synchonized accessprintln(a[0])println(a[1])println(a[2])