Trong thực hành nhanh chóng của tôi, tôi đã viết cấu trúc đơn giản có tên là OrderedSet
.Swift 2: struct thread-safety
Tôi đã thử OrderedSet
là một chuỗi an toàn với hàng đợi nối tiếp GCD.
Nhưng nó không hoạt động. Kết quả thử nghiệm không ổn định. Tôi mong đợi một cái gì đó như:
20:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
nhưng không nhận được cái gì đó như như
2:[3, 19]
đây là mã sân chơi:
import Foundation
import XCPlayground
struct OrderedSet<T: Equatable> {
mutating func append(e: T) {
dispatch_sync(q) {
if !self.__elements.contains(e) {
self.__elements.append(e)
}
}
}
var elements: [T] {
var elements: [T] = []
dispatch_sync(q) {
elements = self.__elements
}
return elements
}
var count: Int {
var ret = 0
dispatch_sync(q) {
ret = self.__elements.count
}
return ret
}
private var __elements: [T] = []
private let q = dispatch_queue_create("OrderedSet.private.serial.queue", DISPATCH_QUEUE_SERIAL)
}
extension OrderedSet: CustomStringConvertible {
var description: String {
var text = ""
dispatch_sync(q) {
text = "\(self.__elements.count):\(self.__elements)"
}
return text
}
}
// Test code
let globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
let group = dispatch_group_create()
var testSet = OrderedSet<Int>()
for i in 0..<20 {
dispatch_group_async(group, globalQueue) {
testSet.append(i)
}
}
dispatch_group_notify(group, globalQueue) {
print("\(testSet)") // unstable result
}
XCPSetExecutionShouldContinueIndefinitely()
Tôi đã kiểm tra dưới đây:
Đó là OK nếu định nghĩa OrderdSet
là một lớp (không phải cấu trúc).
OK nếu sử dụng semaphore thay vì sử dụng hàng đợi nối tiếp.
Tôi muốn biết lý do tại sao cặp cấu trúc và hàng đợi nối tiếp không ổn định.
---- cập nhật
Tôi đã nhận được kết quả mong đợi.
lớp thay vì struct
import Foundation import XCPlayground class OrderedSet<T: Equatable> { func append(e: T) { dispatch_sync(q) { if !self.__elements.contains(e) { self.__elements.append(e) } } } var elements: [T] { var elements: [T] = [] dispatch_sync(q) { elements = self.__elements } return elements } var count: Int { var ret = 0 dispatch_sync(q) { ret = self.__elements.count } return ret } private var __elements: [T] = [] private let q = dispatch_queue_create("OrderedSet.private.serial.queue", DISPATCH_QUEUE_SERIAL) } extension OrderedSet: CustomStringConvertible { var description: String { var text = "" dispatch_sync(q) { text = "\(self.__elements.count):\(self.__elements)" } return text } } // Test code let globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) let group = dispatch_group_create() var testSet = OrderedSet<Int>() for i in 0..<20 { dispatch_group_async(group, globalQueue) { testSet.append(i) } } dispatch_group_notify(group, globalQueue) { print("\(testSet)") // It's OK } XCPSetExecutionShouldContinueIndefinitely()
semaphore thay vì xếp hàng nối tiếp
import Foundation import XCPlayground struct OrderedSet<T: Equatable> { mutating func append(e: T) { dispatch_semaphore_wait(s, DISPATCH_TIME_FOREVER) if !self.__elements.contains(e) { self.__elements.append(e) } dispatch_semaphore_signal(s) } var elements: [T] { var elements: [T] = [] dispatch_semaphore_wait(s, DISPATCH_TIME_FOREVER) elements = self.__elements dispatch_semaphore_signal(s) return elements } var count: Int { var ret = 0 dispatch_semaphore_wait(s, DISPATCH_TIME_FOREVER) ret = self.__elements.count dispatch_semaphore_signal(s) return ret } private var __elements: [T] = [] private let s = dispatch_semaphore_create(1) } extension OrderedSet: CustomStringConvertible { var description: String { var text = "" dispatch_semaphore_wait(s, DISPATCH_TIME_FOREVER) text = "\(self.__elements.count):\(self.__elements)" dispatch_semaphore_signal(s) return text } } // Test code let globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) let group = dispatch_group_create() var testSet = OrderedSet<Int>() for i in 0..<20 { dispatch_group_async(group, globalQueue) { testSet.append(i) } } dispatch_group_notify(group, globalQueue) { print("\(testSet)") // It's OK } XCPSetExecutionShouldContinueIndefinitely()
đợi nối tiếp với OrderdSet riêng của mình.
import Foundation import XCPlayground struct OrderedSet<T: Equatable> { mutating func append(e: T) { if !self.__elements.contains(e) { self.__elements.append(e) } } var elements: [T] { return self.__elements } var count: Int { return self.__elements.count } private var __elements: [T] = [] } extension OrderedSet: CustomStringConvertible { var description: String { return "\(self.__elements.count):\(self.__elements)" } } // Test code let globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) let serialQueue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL) let group = dispatch_group_create() var testSet = OrderedSet<Int>() for i in 0..<20 { dispatch_group_async(group, globalQueue) { dispatch_sync(serialQueue) { testSet.append(i) } } } dispatch_group_notify(group, serialQueue) { print("\(testSet)") // It's OK } XCPSetExecutionShouldContinueIndefinitely()
Vì vậy, triệu chứng là gì? [cách yêu cầu tràn ngăn xếp] (http://stackoverflow.com/help/how-to-ask) – rholmes
kết quả mong đợi của tôi giống như "20: [0, 1, 2, 3, 4, 5, 6, 7 , 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] "nhưng kết quả giống như" 2: [3, 19] ". –
@ tom.e.kid Vui lòng chia sẻ mã thử nghiệm cũng như – Kametrixom