Swiftvariables是primefaces吗?
在Objective-C中,你可以区分primefaces和非primefaces属性:
@property (nonatomic, strong) NSObject *nonatomicObject; @property (atomic, strong) NSObject *atomicObject;
从我的理解中,您可以安全地读取和写入从多个线程定义为primefaces的属性,同时从多个线程写入和访问非primefaces属性或ivars可能会导致未定义的行为,包括访问错误。
所以如果你在Swift中有这样一个variables:
var object: NSObject
我可以安全地并行读写这个variables吗? (不考虑这样做的实际意义)。
现在假设没有低级文档是很早的,但是你可以从汇编中学习。 料斗反汇编是一个伟大的工具。
@interface ObjectiveCar : NSObject @property (nonatomic, strong) id engine; @property (atomic, strong) id driver; @end
分别objc_setProperty_atomic
primefaces和primefaces使用objc_storeStrong
和objc_setProperty_atomic
,其中
class SwiftCar { var engine : AnyObject? init() { } }
使用从libswift_stdlib_core
,显然,没有内置的线程安全。
我们可以推测其他关键字(类似于@lazy
)可能稍后会被引入。
更新07/20/15 :根据这个关于单身 swift环境的博客可以使某些情况对你来说是安全的,即:
class Car { static let sharedCar: Car = Car() // will be called inside of dispatch_once } private let sharedCar: Car2 = Car2() // same here class Car2 { }
更新05/25/16 :留意快速进化的build议https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md – 它看起来像是将可能有自己实现的@atomic
行为。
Swift没有围绕线程安全的语言结构。 假设您将使用提供的库来执行您自己的线程安全pipe理。 在实现线程安全方面有很多选项,包括pthread mutexes,NSLock和dispatch_sync作为互斥体机制。 请参阅Mike Ash最近关于这个主题的文章: https : //mikeash.com/pyblog/friday-qa-2015-02-06-locks-thread-safety-and-swift.html所以直接回答你的问题“Can我安全地并行读写这个variables?“ 没有。
回答这个问题可能会很早。 目前swift缺less访问修饰符,所以没有明显的方法来添加代码来pipe理属性getter / setter的并发性。 而且,Swift语言似乎还没有关于并发的任何信息! (它也缺乏KVO等…)
我认为这个问题的答案将在未来的版本中变得清晰。
细节
xCode 9.1,Swift 4
链接
- apple.developer.com调度
- Grand Central Dispatch(GCD)和Swift 3中的调度队列
- 在Swift中创build线程安全的数组
- Swift中的互斥锁和闭包
primefaces访问的示例
class Atomic { let dispatchGroup = DispatchGroup() private var variable = 0 // Usage of semaphores func semaphoreSample() { // value: 1 - number of threads that have simultaneous access to the variable let atomicSemaphore = DispatchSemaphore(value: 1) variable = 0 runInSeveralQueues { dispatchQueue in // Only (value) queqes can run operations betwen atomicSemaphore.wait() and atomicSemaphore.signal() // Others queues await their turn atomicSemaphore.wait() // Lock access until atomicSemaphore.signal() self.variable += 1 print("\(dispatchQueue), value: \(self.variable)") atomicSemaphore.signal() // Unlock access } notifyWhenDone { atomicSemaphore.wait() // Lock access until atomicSemaphore.signal() print("variable = \(self.variable)") atomicSemaphore.signal() // Unlock access } } // Usage of sync of DispatchQueue func dispatchQueueSync() { let atomicQueue = DispatchQueue(label: "dispatchQueueSync") variable = 0 runInSeveralQueues { dispatchQueue in // Only queqe can run this closure (atomicQueue.sync {...}) // Others queues await their turn atomicQueue.sync { self.variable += 1 print("\(dispatchQueue), value: \(self.variable)") } } notifyWhenDone { atomicQueue.sync { print("variable = \(self.variable)") } } } // Usage of objc_sync_enter/objc_sync_exit func objcSync() { variable = 0 runInSeveralQueues { dispatchQueue in // Only one queqe can run operations betwen objc_sync_enter(self) and objc_sync_exit(self) // Others queues await their turn objc_sync_enter(self) // Lock access until objc_sync_exit(self). self.variable += 1 print("\(dispatchQueue), value: \(self.variable)") objc_sync_exit(self) // Unlock access } notifyWhenDone { objc_sync_enter(self) // Lock access until objc_sync_exit(self) print("variable = \(self.variable)") objc_sync_exit(self) // Unlock access } } } // Helpers extension Atomic { fileprivate func notifyWhenDone(closure: @escaping ()->()) { dispatchGroup.notify(queue: .global(qos: .utility)) { closure() print("All work done") } } fileprivate func runInSeveralQueues(closure: @escaping (DispatchQueue)->()) { async(dispatch: .main, closure: closure) async(dispatch: .global(qos: .userInitiated), closure: closure) async(dispatch: .global(qos: .utility), closure: closure) async(dispatch: .global(qos: .default), closure: closure) async(dispatch: .global(qos: .userInteractive), closure: closure) } private func async(dispatch: DispatchQueue, closure: @escaping (DispatchQueue)->()) { for _ in 0 ..< 100 { dispatchGroup.enter() dispatch.async { let usec = Int(arc4random()) % 100_000 usleep(useconds_t(usec)) closure(dispatch) self.dispatchGroup.leave() } } } }
用法
Atomic().semaphoreSample() //Atomic().dispatchQueueSync() //Atomic().objcSync()
结果