참조
위 글을 보고 간단히 정리한 글, 자세한 내용은 위 블로그 참조 정리퀸이심;
동시성 프로그래밍에서 일어나는 문제 중에 하나인 우선순위의 역전에 대해서 간단히 살펴보겠습니다.
우선순위가 .default, .userInitiated, userInteractive 이렇게 있다고 할 때, 먼저, default 우선순위를 가진 task를 먼저 작업을 실행한다고 가정합니다. 이를 task1로 부르겠슴니다
이런 상황이 있다고 할 때, 문제가 발생하는 경우는 task3가 공유 자원인 a를 사용하는 경우입니다. 이미 a는 task1(default 우선순위)이 점유하고 있기 때문에, task3는 우선순위가 높음에도 불구하고 실행이 멈추게 됩니다.
이 때는 작업의 완료 순서가 (task 2 -> task 1 -> task 3) 순으로 완료됩니다. (a를 점유한 task1이 먼저 종료되는 모습 ~)
이를 우선순위의 역전이라고 합니다. 우선순위가 높은 순대로 종료가 안 되고 있죠
swift는 이를 방지하기 위해 GCD를 사용해 우선순위를 조정하는 모습을 볼 수 있습니다.
위의 경우로 생각을 할 때, default인 task1이 공유 자원을 점유하고 있으니 이 task1을 빨리 끝내야 한다고 판단을하여 우선순위를 올려버립니다. 따라서 task1은 .userInteractive로 우선순위가 조정이 되어서 제일 먼저 작업이 완료가 됩니다.
그런 다음 우선순위가 높은 작업인 task3를 실행하고 완료됩니다. 나머지 task2 도 다음으로 완료됩니다.
이 때의 작업 완료 순서는(task1 -> task3 -> task2) 입니다.
이렇게 GCD에서 자체적으로 처리하는 것 외에도, 공유자원을 접근할 때는 동일한 우선순위를 사용해야 우선순위 역전 문제의 가능성을 줄일 수 있슴니다.
참조
https://github.com/apple/swift/blob/main/docs/SequencesAndCollections.rst#index-protocols
위 문서 읽으면서 괜찮았던 부분을 작성해보려고 함. 자세한 내용은 위 문서 참조 바람
스위프트 깃헙에서 for...in 에서 무슨 작업이 필요할지 정의를 내리고 프로토콜을 작성하는 부분이 있는데 이거 좀 생각하면서 개발하면 좋을듯해서 적어봄
먼저 for...in 반복자의 작업이 뭐가 필요할지 생각해봄 -> 세 가지 작업이 필요함
위 내용을 프로토콜 요구사항으로 그대로 번역하면 다음과 같다
protocol NaiveIteratorProtocol {
typealias Element
var current() -> Element // 현재 요소 가져오기
mutating func advance() // 다음 요소로 진행
var isExhausted: Bool // 더 많은 요소가 있는지 감지
}
그러나 이러한 프로콜은 휘발성 시퀀스(네트워크 패킷 스트림 같은거 순회하면서 소비하는 친구들)에게는 부담을 줍니다.
반복자는 현재 요소를 내부적으로 버퍼링하여 current
가 동일한 값을 반복적으로 반환할 수 있도록 하거나 moveToNext
에 대한 중간 호출 없이 current
가 두 번 호출될때 트랩(chatGPT 선생님 왈 프로그램이 처리할 수 없는 오류나 예외적인 조건으로 인해 프로그램이 의도적으로 강제로 종료되거나 충돌 되는 상황, 두 번 호출되면 종료라는 의미로 받아들이면 될 거 가틈)해야함.
따라서 Swift의 반복자프로토콜은 세 가지 작업을 하나로 병합하여 반복자가 소진되면 nil을 반환한다.
protocol IteratorProtocol {
typealias Element // associatedtype 으로 쓰면 될듯 이젠 ?
mutating func next() -> Element?
}
추가로 정방향(Forward Index), 양방향, 임의 액세스 인덱스 프로토콜을 보게씀다.
순방향은 생략, 얘는 앞으로 전진 하는것과, 끝 지점인지 감지하는 함수가 있으면 된다.
// 양방향은 순방향에서 좀 더 추가된 것
protocol BidirectionalIndexType : ForwardIndexType {
func predecessor() -> Self
}
// 랜덤액세스, 얘는 거리를 알아야함 그리고 음수를 포함하여 더해서 진행가능한지도 알아야한다.
public protocol RandomAccessIndexType : BidirectionalIndexType {
func distance(to other: Self) -> Distance
func advanced(by n: Distance) -> Self
}
임의 액세스 프로토콜은 양방향 프로토콜에서 두 가지 요구사항이 더해진것이다.