我有单身类
class DeviceController:NSObject, CocoaMQTTDelegate {
static let sharedInstance = DeviceController()
var deviceOnArray:[String] = []
var deviceOffArray:[String] = []
private override init() {
clientID = "xyz-" + String(ProcessInfo().processIdentifier)
mqtt = CocoaMQTT(clientID: clientID, host: "device_controller.xyz.net", port: 1883)
mqtt.username = "username"
mqtt.password = "password"
mqtt.willMessage = CocoaMQTTWill(topic: "/will", message: "dieout")
mqtt.keepAlive = 30
mqtt.cleanSession = true
DeviceController.isConnecting = true
super.init()
mqtt.delegate = self
mqtt.connect()
self.registerBackgroundTask()
}
func sendArm(topic:String){
// add device to deviceOnArray
}
func sendDisarm(topic:String){
// remove device from deviceOnArray if exist here if I check by code that device is in array it returns false but on console if print it contains the device, It only heppens when I call sendArm and sendDisarm with a second.
let lockQueue = DispatchQueue(label: "com.test.LockQueue")
lockQueue.sync() {
// all code now inside this
}
// I also used above code but it's not working
}
}
如果您阅读了代码,那么您将知道我在从deviceOnArray / deviceOffArray读取正确值时遇到问题,我不知道如何解释这个问题,但我认为我需要的是Obj-C atomic线程安全变量。知道怎么创造一个吗?
答案 0 :(得分:3)
您可以使用串行调度队列来确保仅以线程安全的方式更新阵列。
最好将deviceOnArray
属性更改为private,以确保其他对象无法访问它。如果需要将此数组公开给其他对象,请通过计算属性执行此操作。 e.g。
class DeviceController:NSObject, CocoaMQTTDelegate {
static let sharedInstance = DeviceController()
private var deviceOnArray:[String] = []
var deviceOn: [String] {
return self.deviceOnArray
}
var deviceOffArray:[String] = []
private let dispatchQueue = DispatchQueue(label:"DeviceControllerQueue")
private override init() {
clientID = "xyz-" + String(ProcessInfo().processIdentifier)
mqtt = CocoaMQTT(clientID: clientID, host: "device_controller.xyz.net", port: 1883)
mqtt.username = "username"
mqtt.password = "password"
mqtt.willMessage = CocoaMQTTWill(topic: "/will", message: "dieout")
mqtt.keepAlive = 30
mqtt.cleanSession = true
DeviceController.isConnecting = true
super.init()
mqtt.delegate = self
mqtt.connect()
self.registerBackgroundTask()
}
func sendArm(topic:String){
// add device to deviceOnArray
self.dispatchQueue.sync {
deviceOnArray.append(topic)
}
}
func sendDisarm(topic:String){
// remove device from deviceOnArray if exist here.
self.dispatchQueue.sync {
if let index = self.deviceOnArray.index(of: topic) {
self.deviceOnArray.remove(at: index)
}
}
}
}
答案 1 :(得分:2)
import Foundation
class AtomicValue<T> {
private let semaphore = DispatchSemaphore(value: 1)
private var _value: T
init (value: T) { _value = value }
//deinit { print("____ \(self) deinited") }
var value: T {
get {
wait(); defer { signal() }
let result = _value
return result
}
set (value) {
wait(); defer { signal() }
_value = value
}
}
func set(closure: ((_ currentValue: T) -> T)?) {
wait(); defer { signal() }
guard let value = closure?(_value) else { return }
_value = value
}
func get(closure: ((_ currentValue: T) -> Void)?) {
wait(); defer { signal() }
closure?(_value)
}
private func wait() { semaphore.wait() }
private func signal() { semaphore.signal() }
}
let atomicValue = AtomicValue(value: 0)
// Usage
print("!\(atomicValue.value)")
atomicValue.value += 1
atomicValue.set { currentValue -> Int in
// Several actions
return currentValue + 1
}
atomicValue.get { currentValue in
// Several actions
print("!\(currentValue)")
}
let atomicValue = AtomicValue(value: 0)
DispatchQueue.global(qos: .utility).async {
(0..<10).forEach { _ in
atomicValue.set { currentValue -> Int in
let newValue = currentValue + 1
print("utility queue: \(newValue)")
return newValue
}
usleep(100_000)
}
}
DispatchQueue.global(qos: .default).async {
(0..<10).forEach { _ in
atomicValue.set { currentValue -> Int in
let newValue = currentValue + 1
print("default queue: \(newValue)")
return newValue
}
usleep(100_000)
}
}
default queue: 1
utility queue: 2
default queue: 3
utility queue: 4
default queue: 5
utility queue: 6
default queue: 7
utility queue: 8
default queue: 9
utility queue: 10
default queue: 11
utility queue: 12
default queue: 13
utility queue: 14
default queue: 15
utility queue: 16
default queue: 17
utility queue: 18
default queue: 19
utility queue: 20
答案 2 :(得分:1)
原子属性对您没有帮助。它们旨在同步分配属性作为整体而不是内部(例如,它们不同步向元素插入/移除元素)。它们几乎只能确保正确的保留/释放/自动释放调用,以防止程序崩溃/泄漏。
您需要的是DispatchSemaphore或类似的内容(或者更多原生内容,posix pthread_mutex
内容)以确保互斥访问。