Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- rxswift
- ios
- 리펙터링
- Protocol
- Clean Code
- Refactoring
- HIG
- RxCocoa
- map
- 리팩토링
- uitableview
- clean architecture
- Observable
- 클린 코드
- uiscrollview
- 애니메이션
- tableView
- UITextView
- Human interface guide
- SWIFT
- ribs
- 스위프트
- swift documentation
- Xcode
- swiftUI
- 리펙토링
- UICollectionView
- MVVM
- collectionview
- combine
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] DispatchSemaphore (세마포어, Critical Section, wait, signal, atopic operation, 동기화) 본문
iOS 응용 (swift)
[iOS - swift] DispatchSemaphore (세마포어, Critical Section, wait, signal, atopic operation, 동기화)
jake-kim 2022. 3. 25. 23:57Semaphore 기본 지식
- 동시에 하나의 자원에 접근을 방지하게 할 수 있는 비동기 문제를 해결하는데 사용
- 여러 프로세스가 데이터를 공유하면서 작업을 수행할 때, 동시에 접근하는 안되는 자원을 동시에 접근할 수 없도록 막는 플래그 기능
* Critical Section: 동시에 접근하는 안되는 자원 - Semaphore는 공유자원에 진입할 수 있는 허용 개수를 의미
- (0이 되면 프로세스들의 공유 자원에 진입하는 것을 막는 것)
var semaphore = 2
// 작업 1 수행
semaphore -= 1 // 현재 semaphore = 1
// 작업 2 수행
semaphore -= 1 // 현재 semaphore = 0
// 작업 3 수행
// 현재 semaphore가 0이므로 대기
Semaphore 연산자
- wait()
- Semaphore의 값이 현재 0보다 크면 값을 -1
- 카운팅 값이 0이되면 값이 증가할 때까지 대기
- 프로세스가 자원을 사용할테니 기다리라는 의미
- signal()
- Semaphore의 값을 +1
- 프로세스가 자원을 사용하고 나왔다는 신호를 의미
swift에서의 Semaphore
- DispatchSemaphore(value:)를 사용
- DispatchSemaphore 인스턴스를 생성
- value: 값은 Semaphore 값을 의미
let semaphore = DispatchSemaphore(value: 1) // 공유자원 최대 1개
var updateSomeProperty = 0 // 예제에 사용될 프로퍼티
- 스위프트 내부적으로 wait()와 signal()의 동작 프로세스
- semaphore값이 0인 상태에서 다른 작업이 들어오면 현재 진행중인 큐에다가 넣어놓고 큐를 대기시키는 것
- 주의: main queue에서 wait()를 사용하고, semaphore가 0이 되었을때, 아래 constraints코드가 안불리는 케이스가 존재
(0...3).forEach { _ in
self.semaphore.wait()
self.addCountAfterSeconds()
self.semaphore.signal()
}
var count = 0
private func addCountAfterSeconds() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.count += 1
}
}
- viewDidLoad에서 wait를 부르는 작업 2가지를 시행
- 작업 1을 실행했을 때 wait()를 한번 하는데, 이때 semaphore = 0이 되어 작업2는 진행 안되는 상황
- 버튼을 눌렀을 때 signal()을 보내서 대기하고 있던 작업2가 동작
- (전체 코드)
class ViewController: UIViewController {
private lazy var someButton: UIButton = {
let button = UIButton()
button.setTitle("semaphore.signal() 실행", for: .normal)
button.setTitleColor(.systemBlue, for: .normal)
button.setTitleColor(.blue, for: .highlighted)
button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(button)
return button
}()
private lazy var someLabel: UILabel = {
let label = UILabel()
label.textColor = .black
label.text = "0"
label.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(label)
return label
}()
let semaphore = DispatchSemaphore(value: 1)
var updateSomeProperty = 0
override func viewDidLoad() {
super.viewDidLoad()
self.executeInCriticalSection()
self.executeInCriticalSection()
NSLayoutConstraint.activate([
self.someButton.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
self.someButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
])
NSLayoutConstraint.activate([
self.someLabel.topAnchor.constraint(equalTo: self.someButton.bottomAnchor, constant: 16),
self.someLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
])
}
private func executeInCriticalSection() {
DispatchQueue.global().async {
self.semaphore.wait()
self.updateSomeProperty += 1
DispatchQueue.main.async {
self.someLabel.text = String(self.updateSomeProperty)
}
}
}
@objc private func didTapButton() {
self.semaphore.signal()
}
}
* 참고
Operating System Concepts (Abraham Silberschatz , Peter B. Galvin , Greg Gagne)
https://developer.apple.com/documentation/dispatch/dispatchsemaphore
'iOS 응용 (swift)' 카테고리의 다른 글
Comments