[concurrency] 스위프트는 Objective-C의“@synchronized”에 해당하는 것은 무엇입니까?

Swift 책을 검색했지만 @synchronized의 Swift 버전을 찾을 수 없습니다. Swift에서 상호 배제를 어떻게합니까?



답변

GCD를 사용할 수 있습니다. 보다 약간 장황 @synchronized하지만 대체 기능으로 작동합니다.

let serialQueue = DispatchQueue(label: "com.test.mySerialQueue")
serialQueue.sync {
    // code
}


답변

나는 이것을 직접 찾고 있었고 아직 이것에 대한 신속한 내부에 네이티브 구성이 없다는 결론에 도달했습니다.

Matt Bridges 및 다른 코드에서 본 코드 중 일부를 기반 으로이 작은 도우미 기능을 구성했습니다.

func synced(_ lock: Any, closure: () -> ()) {
    objc_sync_enter(lock)
    closure()
    objc_sync_exit(lock)
}

사용법은 매우 간단합니다

synced(self) {
    println("This is a synchronized closure")
}

내가 찾은 문제가 하나 있습니다. 잠금 인수로 배열을 전달하면이 시점에서 매우 혼란스러운 컴파일러 오류가 발생하는 것으로 보입니다. 그렇지 않으면 원하는대로 작동하는 것 같습니다.

Bitcast requires both operands to be pointer or neither
  %26 = bitcast i64 %25 to %objc_object*, !dbg !378
LLVM ERROR: Broken function found, compilation aborted!


답변

나는 여기에 많은 답변을 좋아하고 사용하므로 가장 적합한 것을 선택하십시오. 즉, objective-c와 같은 것이 필요할 때 선호하는 방법 은 신속한 2에 도입 된 진술을 @synchronized사용합니다 defer.

{
    objc_sync_enter(lock)
    defer { objc_sync_exit(lock) }

    //
    // code of critical section goes here
    //

} // <-- lock released when this block is exited

이 방법에 대한 좋은 일이, 중요한 부분은 원하는 어떤 방식으로 포함하는 블록을 종료 할 수 있다는 것입니다 (예를 들어, return, break, continue, throw), 그리고 “를 연기 문 내의 문은 프로그램 제어가 전송되는 방식에 상관없이 실행됩니다.” 1


답변

objc_sync_enter(obj: AnyObject?)와 사이에 문을 삽입 할 수 있습니다 objc_sync_exit(obj: AnyObject?). @synchronized 키워드는 표지 아래 해당 방법을 사용하고 있습니다. 즉

objc_sync_enter(self)
... synchronized code ...
objc_sync_exit(self)


답변

@synchronizedObjective-C 의 지시문 아날로그는 rethrowsSwift에서 임의의 반환 유형과 훌륭한 동작을 가질 수 있습니다 .

// Swift 3
func synchronized<T>(_ lock: AnyObject, _ body: () throws -> T) rethrows -> T {
    objc_sync_enter(lock)
    defer { objc_sync_exit(lock) }
    return try body()
}

의 사용 defer문은 직접 임시 변수를 도입하지 않고 값을 반환 할 수 있습니다.


Swift 2에서 @noescape더 많은 최적화를 허용하기 위해 속성을 클로저에 추가하십시오 .

// Swift 2
func synchronized<T>(lock: AnyObject, @noescape _ body: () throws -> T) rethrows -> T {
    objc_sync_enter(lock)
    defer { objc_sync_exit(lock) }
    return try body()
}

GNewc [1] (임의의 리턴 타입이 마음에 드는 곳)과 Tod Cunningham [2] (나는 좋아하는 곳 ) 의 답변을 바탕으로합니다 defer.


답변

스위프트 4

Swift 4에서는 GCD 디스패치 큐를 사용하여 리소스를 잠글 수 있습니다.

class MyObject {
    private var internalState: Int = 0
    private let internalQueue: DispatchQueue = DispatchQueue(label:"LockingQueue") // Serial by default

    var state: Int {
        get {
            return internalQueue.sync { internalState }
        }

        set (newState) {
            internalQueue.sync { internalState = newState }
        }
    }
} 


답변

반환 기능을 추가하려면 다음을 수행하십시오.

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

이어서 다음을 사용하여 호출 할 수 있습니다.

func importantMethod(...) -> Bool {
  return synchronize(self) {
    if(feelLikeReturningTrue) { return true }
    // do other things
    if(feelLikeReturningTrueNow) { return true }
    // more things
    return whatIFeelLike ? true : false
  }
}