NSKeyedArchiver
을 사용하여 보관하려는 Set<CostumObject>
유형의 인스턴스가 있습니다.사용자 정의 개체 집합을 스레드로부터 안전하게 보관하는 방법은 무엇입니까?
customObject1: CostumObject
및 customObject2: CostumObject
이 어딘가에 인스턴스화된다고 가정하십시오.
나는 다음과 같은 문을 사용하는 경우 :
let setOfCostomObjects: Set<CostumObject> = [customObject1, customObject2]
let data = NSKeyedArchiver.archivedData(withRootObject: setOfCostomObjects)
NSKeyedArchiver
아카이브 순차적으로 그 특성이 반복적으로 보관 모두 사용자 정의 개체를.
다른 스레드가 보관 중에 사용자 지정 개체와 해당 속성을 모두 변경할 수 있으므로 스레드로부터 안전하지 않습니다.
private let concurrentPropertyAccessQueue = DispatchQueue(label: "concurrentPropertyAccessQueue", attributes: .concurrent)
…
private var safeProperty = CostumProperty.init()
public private(set) var property: CostumProperty {
get {
var result = CostumProperty.init()
concurrentPropertyAccessQueue.sync { result = safeProperty } // sync, because result is returned
return result
} // get
set { concurrentPropertyAccessQueue.async(flags: .barrier) { safeProperty = newValue } // executes locked after all gets
} // set
}
…
public func threadSafeArchiveOfProperty() -> Data {
var data = Data.init()
concurrentPropertyAccessQueue.sync { // sync, because result is returned
data = NSKeyedArchiver.archivedData(withRootObject: self.safeProperty)
}
return data
}
:
은 내가 스레드 안전 할 수 아카이브를 사용자 정의 개체의 각 속성, 즉 동시 같은 세트에 대한 장벽으로 동시 큐를 사용하여 허용하지만, 단 하나의 세트된다됩니다 그렇게 생각 나는 또한 스레드 안전 할 수 아카이브를 전체 사용자 지정 개체를 비슷한 방법으로 생각 :
private let concurrentObjectAccessQueue = DispatchQueue(label: "concurrentObjectAccessQueue", attributes: .concurrent)
…
public func encode(with aCoder: NSCoder) {
concurrentObjectAccessQueue.async(execute: {
aCoder.encode(self.property forKey: "property")
…
})
}
문제는 여전히 아카이브 사용자 정의 객체의 집합을 안전을 스레드하는 방법이다.
이렇게하면 아카이브하는 동안 집합 요소에 대한 쓰기 액세스가 잠길 수 있습니다. 하나는 아마 func threadSafeArchiveOfSet()
를 정의하는 Set
유형의 확장을 쓸 수
public let globalConcurrentAccessQueue = DispatchQueue(label: "globalConcurrentAccessQueue", attributes: .concurrent)
이 설정 및 보관 동안 모든 요소를 잠 그려면 : 그렇게 할
한 가지 방법은 글로벌 동시 큐를 정의하는 아마 위와 같이.
이 함수는 globalConcurrentAccessQueue
이 잠길 수 있도록 Set의 encode(with aCoder: NSCoder)
을 덮어 씁니다.
이것이 올바른 방법인가요?
표준 해결책이 있어야하는 표준 문제라고 생각합니다.
@Rob 빠른 답장을 보내 주셔서 감사합니다. 나는 그들을 이해해야하고, 다시 올 것이다. –
@Rob 속성 수준 동기화에 관해서 : 당신은 완전히 옳았습니다 : 개체를 전체적으로 일관되게 유지하려면 개체 또는 개체의 모든 속성을 개체 수준에서 동기화해야하며 속성 수준의 동기화는 더 이상 사용되지 않습니다. 비동기 인코딩과 관련 : 당신은 다시 생각해 보았습니다. 호출자 인 NSKeyedArchiver는 모든 개별 아카이브 결과가 하나의 최종 데이터 객체에 결합되므로 인코딩이 순차적 프로세스라고 가정합니다. –
@Rob 싱크 패턴의 단순화에 관해서 : 흥미 롭다! 나는 이것을 몰랐다. 제안이 작동하지만 [docs] (https://developer.apple.com/documentation/dispatch/dispatchqueue/1452870-sync)에서 찾을 수 없습니다. 동기화하지 말아야 반환 값이 있습니까? –