在Swift中创建线程安全数组

我在Swift中遇到了线程问题。我有一些对象的数组。通过委托,该类大约每秒钟获取一个新对象。之后,我必须检查对象是否已经在数组中,因此我必须更新对象,否则必须删除/添加新对象。

如果添加新对象,则必须首先通过网络获取一些数据。这是通过块进行的。

现在我的问题是,我该如何同步这些任务?

我试过了dispatch_semaphore,但是这个阻塞了UI,直到阻塞完成。

我还尝试了一个简单的bool变量,该变量检查当前是否正在执行该块,并同时跳过compare方法。

但是两种方法都不理想。

管理阵列的最佳方法是什么,我不想在阵列中有重复的数据。


茅侃侃
浏览 971回答 3
3回答

POPMUISE

Kirsteins是正确的,但是您并不总是需要使用调度队列。您可以使用:objc_sync_enter(array)// manipulate the arrayobjc_sync_exit(array)这应该可以解决问题。为了获得更多好处,您可以创建一个需要线程安全时使用的函数:func sync(lock: NSObject, closure: () -> Void) {    objc_sync_enter(lock)    closure()    objc_sync_exit(lock)}...var list = NSMutableArray()sync (list) {   list.addObject("something")}请注意,我已更改AnyObject为NSObject。在Swift集合中,类型被实现为structs,并通过value传递,因此我猜想使用方便的函数时,使用通过引用传递的可变集合类会更安全。syncSwift更新线程安全访问的推荐模式是使用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

白猪掌柜的

我解决此问题的方法是使用串行分派队列,以同步对盒装阵列的访问。当您尝试获取索引值并且队列确实很忙时,它将阻塞线程,但这也是锁的问题。public class SynchronizedArray<T> {&nbsp; &nbsp; private var array: [T] = []&nbsp; &nbsp; private let accessQueue = dispatch_queue_create("SynchronizedArrayAccess", DISPATCH_QUEUE_SERIAL)&nbsp; &nbsp; public func append(newElement: T) {&nbsp; &nbsp; &nbsp; &nbsp; dispatch_async(self.accessQueue) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.array.append(newElement)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public subscript(index: Int) -> T {&nbsp; &nbsp; &nbsp; &nbsp; set {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dispatch_async(self.accessQueue) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.array[index] = newValue&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; get {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var element: T!&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dispatch_sync(self.accessQueue) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; element = self.array[index]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return element&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}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])

开心每一天1111

Kirsteins的答案是正确的,但是为了方便起见,我使用Amol Chaudhari和Rob的建议更新了该答案,他建议使用带有异步屏障的并发队列来允许并发读取但阻止写入。我还包装了一些对我有用的其他数组函数。public class SynchronizedArray<T> {private var array: [T] = []private let accessQueue = dispatch_queue_create("SynchronizedArrayAccess", DISPATCH_QUEUE_CONCURRENT)public func append(newElement: T) {&nbsp; &nbsp; dispatch_barrier_async(self.accessQueue) {&nbsp; &nbsp; &nbsp; &nbsp; self.array.append(newElement)&nbsp; &nbsp; }}public func removeAtIndex(index: Int) {&nbsp; &nbsp; dispatch_barrier_async(self.accessQueue) {&nbsp; &nbsp; &nbsp; &nbsp; self.array.removeAtIndex(index)&nbsp; &nbsp; }}public var count: Int {&nbsp; &nbsp; var count = 0&nbsp; &nbsp; dispatch_sync(self.accessQueue) {&nbsp; &nbsp; &nbsp; &nbsp; count = self.array.count&nbsp; &nbsp; }&nbsp; &nbsp; return count}public func first() -> T? {&nbsp; &nbsp; var element: T?&nbsp; &nbsp; dispatch_sync(self.accessQueue) {&nbsp; &nbsp; &nbsp; &nbsp; if !self.array.isEmpty {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; element = self.array[0]&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return element}public subscript(index: Int) -> T {&nbsp; &nbsp; set {&nbsp; &nbsp; &nbsp; &nbsp; dispatch_barrier_async(self.accessQueue) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.array[index] = newValue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; get {&nbsp; &nbsp; &nbsp; &nbsp; var element: T!&nbsp; &nbsp; &nbsp; &nbsp; dispatch_sync(self.accessQueue) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; element = self.array[index]&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return element&nbsp; &nbsp; }}}UPDATE 这是相同的代码,为Swift3更新。public class SynchronizedArray<T> {private var array: [T] = []private let accessQueue = DispatchQueue(label: "SynchronizedArrayAccess", attributes: .concurrent)public func append(newElement: T) {&nbsp; &nbsp; self.accessQueue.async(flags:.barrier) {&nbsp; &nbsp; &nbsp; &nbsp; self.array.append(newElement)&nbsp; &nbsp; }}public func removeAtIndex(index: Int) {&nbsp; &nbsp; self.accessQueue.async(flags:.barrier) {&nbsp; &nbsp; &nbsp; &nbsp; self.array.remove(at: index)&nbsp; &nbsp; }}public var count: Int {&nbsp; &nbsp; var count = 0&nbsp; &nbsp; self.accessQueue.sync {&nbsp; &nbsp; &nbsp; &nbsp; count = self.array.count&nbsp; &nbsp; }&nbsp; &nbsp; return count}public func first() -> T? {&nbsp; &nbsp; var element: T?&nbsp; &nbsp; self.accessQueue.sync {&nbsp; &nbsp; &nbsp; &nbsp; if !self.array.isEmpty {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; element = self.array[0]&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return element}public subscript(index: Int) -> T {&nbsp; &nbsp; set {&nbsp; &nbsp; &nbsp; &nbsp; self.accessQueue.async(flags:.barrier) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.array[index] = newValue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; get {&nbsp; &nbsp; &nbsp; &nbsp; var element: T!&nbsp; &nbsp; &nbsp; &nbsp; self.accessQueue.sync {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; element = self.array[index]&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return element&nbsp; &nbsp; }}}
打开App,查看更多内容
随时随地看视频慕课网APP