3 回答

TA貢獻(xiàn)1765條經(jīng)驗(yàn) 獲得超5個(gè)贊
Kirsteins是正確的,但是您并不總是需要使用調(diào)度隊(duì)列。您可以使用:
objc_sync_enter(array)
// manipulate the array
objc_sync_exit(array)
這應(yīng)該可以解決問(wèn)題。為了獲得更多好處,您可以創(chuàng)建一個(gè)需要線程安全時(shí)使用的函數(shù):
func sync(lock: NSObject, closure: () -> Void) {
objc_sync_enter(lock)
closure()
objc_sync_exit(lock)
}
...
var list = NSMutableArray()
sync (list) {
list.addObject("something")
}
請(qǐng)注意,我已更改AnyObject為NSObject。在Swift集合中,類型被實(shí)現(xiàn)為structs,并通過(guò)value傳遞,因此我猜想使用方便的函數(shù)時(shí),使用通過(guò)引用傳遞的可變集合類會(huì)更安全。sync
Swift更新
線程安全訪問(wèn)的推薦模式是使用dispatch barrier:
let queue = DispatchQueue(label: "thread-safe-obj", attributes: .concurrent)
// write
queue.async(flags: .barrier) {
// perform writes on data
}
// read
var value: ValueType!
queue.sync {
// perform read and assign value
}
return value

TA貢獻(xiàn)1893條經(jīng)驗(yàn) 獲得超10個(gè)贊
我解決此問(wèn)題的方法是使用串行分派隊(duì)列,以同步對(duì)盒裝陣列的訪問(wèn)。當(dāng)您嘗試獲取索引值并且隊(duì)列確實(shí)很忙時(shí),它將阻塞線程,但這也是鎖的問(wèn)題。
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 access
println(a.array)
// thread-safe synchonized access
println(a[0])
println(a[1])
println(a[2])

TA貢獻(xiàn)1836條經(jīng)驗(yàn) 獲得超13個(gè)贊
Kirsteins的答案是正確的,但是為了方便起見(jiàn),我使用Amol Chaudhari和Rob的建議更新了該答案,他建議使用帶有異步屏障的并發(fā)隊(duì)列來(lái)允許并發(fā)讀取但阻止寫(xiě)入。
我還包裝了一些對(duì)我有用的其他數(shù)組函數(shù)。
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
}
}
}
UPDATE 這是相同的代碼,為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
}
}
}
添加回答
舉報(bào)