defer로 인해 lock의 범위가 넓어져 발생한 문제 분석
동시성 코드에서 lock은 가장 직관적인 장치 중 하나로 여러 스레드가 같은 상태를 동시에 읽고 쓰면 race condition이 발생할 수 있기 때문에 공유 자원을 보호하기 위해 lock을 사용.
문제는 아래의 코드 패턴은 락의 범위를 함수 끝까지 늘려서 이 경우 후속 로직에서 lock을 다시 잡아야 하는 코드가 존재면 문제가 발생할 수 있음.
func foo() {
lock.lock()
defer { lock.unlock() }
// do something
}
문제가 발생하는 코드 예시
락을 잡은 채 기다리는 구조가 생기면 장기 대기나 데드락으로 이어질 수 있음.
특히 코드와 로직이 복잡할수록 원인이 코드 한가운데에 숨어 있어 발견하기 어려움.
func someFunction() {
lock.lock()
defer { lock.unlock() }
// 상태 변경
isCompleted = false
// callback이 signal 해줘야 함
finished.wait()
}
func callback() {
lock.lock()
defer { lock.unlock() }
// 상태 변경
isCompleted = true
finished.signal()
}
lock은 상태만 보호하기
락의 역할은 공유 상태를 안전하게 읽고 쓰는 것이 목적이라서 가급적 짧게 유지해야 함.
defer로 lock 범위가 넓어진 상태에서 오래 기다릴 수 있는 작업까지 임계구역에 들어갈 경우 lock이 상태 보호의 도구를 넘어 흐름을 차단하는 장치로 동작하게 됨.
따라서 lock은 상태를 보호하기 위해서 짧게 사용하고, 대기하는 작업은 반드시 lock 밖에서 사용하기.
'project > 개발 업무' 카테고리의 다른 글
| 기기별 RAM 용량에 따른 이미지 동적 캐시 사이즈 설계 (0) | 2026.03.25 |
|---|---|
| UNUserNotificationCenter `requestAuthorization`에서 발생하는 희귀한 버그 현상 분석 (0) | 2025.10.27 |
| l-value, r-value (0) | 2025.10.23 |
| Actor에서 Class + OSAllocatedUnfairLock (2) | 2025.08.06 |
| Swift Concurrency Task weak self 실험 정리 (0) | 2025.07.29 |