본 게시물은 앨런의 인프런 강의를 듣고 작성한 글 입니다.
작업을 처리하는 과정에서 2개의 스레드가 동시에 메모리에 접근할 수 있다. 이러한 상황에서 문제가 생기는데..
이런 문제는 Thread-Safety를 통해 해결할 수 있다. 단어의 뜻 그대로 스레드를 안전하게 사용한다. 여러 스레드를 동시에 사용한다고 해도 문제가 생기지 않고 안전하게 사용할 수 있다. 한번에 한개의 스레드만 자원에 접근할 수 있게 하여 경쟁상황을 발생시키지 않고 안전하게 사용한다. 이렇게 사용함을 Thread-Safety하게 코드를 작성했다고 한다.
1. 경쟁상황 (Race Condition)
var a = 1
DispatchQueue.global().async {
sleep(1)
a += 1
}
DispatchQueue.global().async {
sleep(1)
a += 1
}
print(a)
위와 같은 코드를 실행하면 디스패치큐에 작업을 보내는 과정에서 문제가 생긴다.
현재 비동기적으로 작업을 처리하고 있기 때문에 작업결과를 확인하지 않고 바로 반환되어 다음 코드를 실행한다.
첫번째 작업에서 a는 1이고, 이 1이라는 값에 대해 1을 더한다.
두번째 작업에서 내가 원하는 과정은 위에서 계산한 결과인 2에 1을 더해 3을 출력하는게 목표지만, 두번째 작업은 a가 1인 상태에서 값을 불러와 더하기 때문에 결과적으로 2라는 값이 출력되어 예상과 다른 결과를 도출한다.
두 작업이 각각 다른 스레드에 배치되어 하나의 메모리에 접근하여 작업을 처리하기 때문에 이 과정에서 문제가 생기는 것이다.
2. 교착상태 (Deadlock)
2개의 메모리를 각각 다른 스레드에 배치하여 작업을 처리하는 과정에서..
하나의 자원에 2개 이상의 스레드가 접근하는 것을 방지하기 위해 스레드에 작업이 배치되면 다른 스레드의 접근을 막는다.
이런 과정에서 작업이 각각 독립적으로 실행된다면 괜찮지만 이 작업이 서로에게 영향을 준다면, 서로의 접근을 막은 상황이 발생하기 때문에 교착상태가 발생한다. 작업이 이러지도 저러지도 못하고 진행이 되지 않는 상태를 의미한다.
이런 교착상태는 1) 동기 작업이 현재 스레드가 필요한 경우, 2) 앞선 작업이 현재의 스레드가 필요한 경우, 3) 여러개의 세마포어가 존재할 때(잘못된 순서 설계)와 같은 상황에 발생할 가능성이 있다.
이 문제는 어떻게 해결할까? 시리얼 큐로 해결할 수 있다. 그러나 세마포어나 제한된 리소스 순서 같은것을 조심히 사용해야하고, 객체등을 설계할때 주의해야 한다.
3. 우선 순위의 뒤바뀜 (Prioirty Inversion)
메모리a라는 자원은 한개의 스레드에서 접근중이면 다른 스레드에서 접근할 수 없다.
따라서 Thread4에 배치되면 메모리a에 다른 스레드는 접근할 수 없고, task1은 우선순위가 더 높은 task2를 처리하기 위해 잠시 멈춘다.
task2는 처리 중 task3이 더 우선순위가 높기 때문에 이를 처리하기 위해 멈추게 되고, task3을 처리한다.
그러나 메모리a는 하나의 스레드만 접근할 수 있기 때문에 task3이 멈추게 되고, task2가 원래라면 처리되어야 하지만 GCD가 이를 알아서 우선순위를 조정하기 때문에 가장 우선순위가 되는 task3을 처리하기 위해 방해(?)가 되는 task1을 먼저 처리하고 task3을 처리하고 task2를 처리한다. (task1 -> task3 -> task2)
우선순위가 높은 task3이 가장 먼저 처리되어야했지만 task1이 가장 먼저 처리되었다. 이런 우선순위의 뒤바뀜이 생길 수 있다.
이런 우선순위는 1) 시리얼큐에서 높은 우선순위 작업이 낮은 우선순위 뒤에 보내지는 경우, 2) 낮은 우선순위의 작업이 높은 우선순위가 필요한 자원을 잠그고 있는 경우(lock, 세마포어), 3) 높은 우선순위 작업이 낮은 작업에 의전하는 경우(Operation)에 발생한다.
이런 문제는 1차적으로는 GCD가 우선순위를 조정해서 알아서 해결한다! (위와 같이..)
그리고 위 그림에서 Qos가 각각 달랐지만 동일한 Qos를 사용하면 문제가 생길 가능성을 줄일 수 있다.
'iOS' 카테고리의 다른 글
[iOS] 델리게이트 패턴 (Delegate Pattern) (0) | 2023.03.18 |
---|---|
[iOS] OAuth Login firebase와 연동하면서 알게된 점 (Apple, Google, Email, Kakao) (0) | 2022.12.23 |
[iOS] 디스패치 그룹(Dispatch Group) (0) | 2022.12.13 |
[iOS] 디스패치큐(GCD) 사용 시 주의해야할 사항 (0) | 2022.12.11 |
[iOS] 디스패치큐(GCD)의 종류와 특성 (메인큐, 글로벌큐, 프라이빗큐) (0) | 2022.12.07 |