What is the Swift equivalent to Objective-C's

2019-01-04 15:30发布

I've searched the Swift book, but can't find the Swift version of @synchronized. How do I do mutual exclusion in Swift?

17条回答
相关推荐>>
2楼-- · 2019-01-04 16:11

Swift 3

This code has the re-entry ability and can work with Asynchronous function calls. In this code, after someAsyncFunc() is called, another function closure on the serial queue will process but be blocked by semaphore.wait() until signal() is called. internalQueue.sync shouldn't be used as it will block the main thread if I'm not mistaken.

let internalQueue = DispatchQueue(label: "serialQueue")
let semaphore = DispatchSemaphore(value: 1)

internalQueue.async {

    self.semaphore.wait()

    // Critical section

    someAsyncFunc() {

        // Do some work here

        self.semaphore.signal()
    }
}

objc_sync_enter/objc_sync_exit isn't a good idea without error handling.

查看更多
看我几分像从前
3楼-- · 2019-01-04 16:12

Use GCD. It is a little more verbose than @synchronized, but works perfectly well as a replacement:

let serialQueue = DispatchQueue(label: "com.test.mySerialQueue")
serialQueue.sync {
    // code
}
查看更多
forever°为你锁心
4楼-- · 2019-01-04 16:13

Why make it difficult and hassle with locks? Use Dispatch Barriers.

A dispatch barrier creates a synchronization point within a concurrent queue.

While it’s running, no other block on the queue is allowed to run, even if it’s concurrent and other cores are available.

If that sounds like an exclusive (write) lock, it is. Non-barrier blocks can be thought of as shared (read) locks.

As long as all access to the resource is performed through the queue, barriers provide very cheap synchronization.

查看更多
叛逆
5楼-- · 2019-01-04 16:14

You can sandwich statements between objc_sync_enter(obj: AnyObject?) and objc_sync_exit(obj: AnyObject?). The @synchronized keyword is using those methods under the covers. i.e.

objc_sync_enter(self)
... synchronized code ...
objc_sync_exit(self)
查看更多
Root(大扎)
6楼-- · 2019-01-04 16:14

Use NSLock in Swift4:

let lock = NSLock()
lock.lock()
if isRunning == true {
        print("Service IS running ==> please wait")
        return
} else {
    print("Service not running")
}
isRunning = true
lock.unlock()

Warning The NSLock class uses POSIX threads to implement its locking behavior. When sending an unlock message to an NSLock object, you must be sure that message is sent from the same thread that sent the initial lock message. Unlocking a lock from a different thread can result in undefined behavior.

查看更多
女痞
7楼-- · 2019-01-04 16:15

To add return functionalty, you could do this:

func synchronize<T>(lockObj: AnyObject!, closure: ()->T) -> T
{
  objc_sync_enter(lockObj)
  var retVal: T = closure()
  objc_sync_exit(lockObj)
  return retVal
}

Subsequently, you can call it using:

func importantMethod(...) -> Bool {
  return synchronize(self) {
    if(feelLikeReturningTrue) { return true }
    // do other things
    if(feelLikeReturningTrueNow) { return true }
    // more things
    return whatIFeelLike ? true : false
  }
}
查看更多
登录 后发表回答