관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] NSLock과 NSRecursiveLock의 차이 (Critical Section, 멀티 스레드 프로그래밍, thread safe) 본문

iOS 응용 (swift)

[iOS - swift] NSLock과 NSRecursiveLock의 차이 (Critical Section, 멀티 스레드 프로그래밍, thread safe)

jake-kim 2023. 5. 4. 00:14

Critical Section(크리티컬 섹션)

  • 한 번에 둘 이상의 스레드가 접근하면 안되는 공유 자원 영역

ex) 멀티 스레드로 처리하는 Data가 있을 때 set이 동시에 이루어지면 안되므로 이 구역을 Critical Section이라고 명칭

NSLock, NSRecursiveLock 개념

  • NSLock
    • 하나의 스레드 혹은 둘 이상의 스레드가 lock()이 있는 다음 코드 부분을 접근하지 못하도록 상호배제하는 방법
    • critical section에 들어갈때 lock()을 걸고 작업을 끝내면 unlock() 호출하는 방법
  • NSRecursiveLock
    • 둘 이상의 스레드가 lock()이 있는 다음 코드 부분을 접근하지 못하도록 상호배제하는 방법
  • NSLock과 NSRecursiveLock 차이
    • NSRecursiveLock는 A 스레드가 lock을 걸었을 때, A 스레드가 다시 해당 부분에 접근할 때 lock을 다시 걸을 수 있음

ex) 코드로 NSLock과 NSRecursiveLock 구분하기

  • global queue는 concurrent queue이므로 critical section에서 상호배제 처리가 필요하므로 lock 사용
func example1() {
    let lock = NSLock()

    DispatchQueue.global().async {
        lock.lock()
        print("Thread 1 is in critical section")
        lock.unlock()
    }

    DispatchQueue.global().async {
        lock.lock()
        print("Thread 2 is in critical section")
        lock.unlock()
    }
}
  • 같은 스레드가 lock을 통과시키고 싶으면 NSRecursiveLock()을 사용
func example2() {
    let recursiveLock = NSRecursiveLock()

    func recursiveFunction(count: Int) {
        recursiveLock.lock()
        if count > 0 {
            print("Count is \(count)")
            recursiveFunction(count: count - 1)
        }
        recursiveLock.unlock()
    }

    recursiveFunction(count: 3)
}


/*
Count is 1
Count is 2
Count is 3
*/
  • 만약 위 상황에서 NSLock을 사용하면 영원히 lock 되어있음
func example3() {
    let recursiveLock = NSLock()

    func recursiveFunction(count: Int) {
        recursiveLock.lock()
        if count > 0 {
            print("Count is \(count)")
            recursiveFunction(count: count - 1)
        }
        recursiveLock.unlock()
    }

    recursiveFunction(count: 3)
}

/*
Count is 3
... deadlock!
*/

결론

  • 같은 스레드에서는 lock을 걸 필요가 없을때는 NSRecursiveLock을 사용할 것

* 전체 코드: https://github.com/JK0369/ExLock

* 참고

https://developer.apple.com/documentation/foundation/nsrecursivelock

https://developer.apple.com/documentation/foundation/nslock

Comments