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
- tableView
- MVVM
- Clean Code
- combine
- Observable
- Protocol
- map
- 리펙토링
- Refactoring
- HIG
- rxswift
- collectionview
- swift documentation
- 스위프트
- clean architecture
- swiftUI
- Human interface guide
- uitableview
- uiscrollview
- 리펙터링
- 클린 코드
- 애니메이션
- Xcode
- ios
- UICollectionView
- UITextView
- 리팩토링
- ribs
- RxCocoa
- SWIFT
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 비동기 작업에서의 안전한 get, set 설정 방법, read/write lock (GCD barrier flags) 본문
iOS 응용 (swift)
[iOS - swift] 비동기 작업에서의 안전한 get, set 설정 방법, read/write lock (GCD barrier flags)
jake-kim 2021. 7. 2. 23:17* Sync vs Async vs Serial vs Concurrent 개념: https://ios-development.tistory.com/1082
GCD(Grand Central Dispatch)
- 쓰레드의 최상위에 만들어지며 공유된 Thread pool을 관리하여 thread safe 유지
- GCD의 개념 참고
Queue 생성
- DispatchQueue.global() 사용: 이미 존재하는 concurrent queue만 사용
- DispatchQueue.init(label:qos:attributtes:) 사용: 우선순위, serial, concurrent 새롭게 사용 가능
global이 아닌 .init(label:qos:attributtes:)를 사용할때의 장점
- 디버깅에 용이: break point를 걸고 디버깅에서 label값을 가지고 어떤 큐에서 동작하는지 파악이 용이
- queue가 많아졌을때 label을 통해 구분 용이
- global queue는 특정 label을 알 수 없기 때문에 디버깅에 힘들고 concurrent queue만 존재
Dispatch Barrier
- Concurrent하게 일이 수행되다가 flag가 barrier로 설정된 작업이 실행되면 그 작업이 끝날때까지 Serial queue처럼 동작
- ex)
let myQueue = DispatchQueue(label: "myQueue", attributes: .concurrent)
for i in 1...5 {
myQueue.async {
print("\(i)")
}
}
myQueue.async(flags: .barrier) {
print("barrier!!")
sleep(5)
}
for i in 6...10 {
myQueue.async {
print("\(i)")
}
}
//
3
1
4
5
2
barrier!!
6
7
10
8
9
비동기 작업에서의 안전한 get, set 설정 방법
- Barrier flag 사용
- ex) API 요청 > AccessToken 만료 > Refresh Token 갱신 api 요청하는 상황
(만약 refresh token도 만료되었다면 splash화면으로 이동)- API를 요청하는 것은 비동기적이므로, AccessToken이 만료되었을때 refresh token을 요청하는 부분이 한순간에 다수가 요청하게 되는 점 존재
- 다수가 요청하면서 refresh token은 실제로 만료가 되지 않았지만, 여러번 요청으로 인해 서버에 refreshToken이 갱신된 상태에서 또 다른 요청이 이전의 refresh token으로 request를 날리면서 'refresh token 유효 하지 않음' 응답을 받는 상황 발생
- flag값이 필요하여 아래와 같이 정의
- get: queue.sync 사용
- set: queue.async(flags: .barrier) 사용
- get에서는 sync를 사용하고 set에서는 async를 사용하는 이유는 성능 때문 (자세한 개념은 이 포스팅 글 참고)
public protocol ServiceStatusStore {
var isPossibleEntry: Bool { get set }
var isInvalidRefreshToken: Bool { get set }
}
final class DefaultServiceStatusStore: ServiceStatusStore {
public static let shared = DefaultServiceStatusStore()
private init() {}
private var _isPossibleEntry = true
private var _isInvalidRefreshToken = false
private var queue = DispatchQueue(label: "status.queue", attributes: .concurrent)
var isPossibleEntry: Bool {
get {
return queue.sync {
return _isPossibleEntry
}
}
set {
queue.async(flags: .barrier) {
self._isPossibleEntry = newValue
}
}
}
var isInvalidRefreshToken: Bool {
get {
return queue.sync {
return _isInvalidRefreshToken
}
}
set {
queue.async(flags: .barrier) {
self._isInvalidRefreshToken = newValue
}
}
}
}
* 참고
'iOS 응용 (swift)' 카테고리의 다른 글
Comments