티스토리 뷰
https://developer.apple.com/documentation/dispatch/dispatchsemaphore
DispatchSemaphore
전형적인 카운팅 세마포어를 사용하여 여러 실행구문에서 공유하는 리소스에 대한 접근을 제어하는 객체.
세마포어는 한글로 신호기/신호등 정도로 해석이 가능하다.
선언
class DispatchSemaphore : DispatchObject
개요
디스패치 세마포어는 전형적인 카운팅 세마포어의 효율적인 구현이다. 디스패치 세마포어는 실행중인 쓰레드를 블록해야 할 때만 커널을 호출한다. 만약 세마포어가 블록할 필요가 없다면 커널 호출은 발생되지 않는다.
signal() 메소드 호출로 세마포어 카운트를 올리고, wait() 메소드 호출 또는 시간제한 두기를 통해 세마포어 카운트를 내릴 수 있다.
요약
한정된 공유자원에 접근하기 위해 카운팅 세마포어를 사용해 과도한 동시 접근을 막을 수 있다.
활용
wait()는 카운트가 0이면 1 이상이 될 때까지 동기적으로 대기한다. 그리고 대기가 끝나 실행을 하게되면 카운트를 1 줄여 공유자원 접근을 시작했음을 카운팅한다. 그리고 signal()은 카운트를 1 증가시켜 공유자원 접근이 끝남을 카운팅한다.
// 동시에 하나만 접근이 가능한 세마포어를 생성한다.
let semaphore = DispatchSemaphore(value: 1)
DispatchQueue.global().async {
semaphore.wait()
print("작업1: 공유자원 접근 시작")
sleep(1)
print("작업1: 공유자원 접근 종료")
semaphore.signal()
}
DispatchQueue.global().async {
semaphore.wait()
print("작업2: 공유자원 접근 시작")
sleep(2)
print("작업2: 공유자원 접근 종료")
semaphore.signal()
}
// 출력
// 작업1: 공유자원 접근 시작
// 작업1: 공유자원 접근 종료
// 작업2: 공유자원 접근 시작
// 작업2: 공유자원 접근 종료
// 0s: 작업1 공유자원 접근 시작 및 작업2 대기
// 1s: 작업1 공유자원 접근 종료 후 작업2 공유자원 접근 시작
// 3s: 작업2 공유자원 접근 종료
공유자원 사용이 종료되지 않고 너무 오래지속되는 경우를 대비하여 wait(timeout:)을 통해 시간 제한을 둘 수 있다. 또한 시간제한 내에 완료 여부를 알 수도 있다.
let timeoutResult = semaphore.wait(timeout: .now() + 5)
비동기 함수가 있을 때 동기적으로 실행하게 만들 수도 있다. 세마포어 카운트를 처음부터 0으로 두어 대기하다가 비동기 함수가 종료될 때 signal()을 호출하여 코드 실행을 지속하면 된다.
var file: Data?
let semaphore = DispatchSemaphore(value: 0)
let url = URL(string: "https://example.com/file")!
let task = URLSession.shared.dataTask(with: url) { data, _, _ in
file = data
// 비동기 함수가 끝날 때 signal()을 호출
semaphore.signal()
}
task.resume()
semaphore.wait()
print(file)'Swift 이론' 카테고리의 다른 글
| Swift에서 날짜를 다루는 다양한 방법 알아보기 (0) | 2022.08.24 |
|---|---|
| AsyncStream으로 콜백과 델리게이트 async-await 변환 (Swift) (0) | 2022.07.30 |
| Continuation을 이용하여 컴플리션 핸들러, 델리게이트 패턴을 async 함수로 변환하기 (Swift) (0) | 2022.06.27 |
| DispatchGroup 사용하기 (Swift) (0) | 2022.05.01 |
