<@Sendable은 무엇인가?> 3. actor란 무엇인가?

SteadySlower·2023년 7월 7일
0

iOS Development

목록 보기
25/38

저번 포스팅까지 Sendable에 대해서 배웠는데요. 이번 포스팅에서는 actor에 대해서 알아보도록 하겠습니다.

Actor의 정의

저번 포스팅에서 actor를 통해서 쉽게 Sendable Protocol을 준수할 수 있다는 이야기를 했었는데요. 잠시 배경 설명을 하자면 Sendable Protocol은 멀티스레딩 환경에서 Race Condition을 일으키지 않는 것을 보장하는 Protocol이었습니다. 그리고 Race condition의 원인은 Shared Mutable State였구요.

하지만 Shared Mutable State가 필요한 경우에는 어떻게 할까요? 즉 class로 구현된 타입을 멀티스레딩에 활용해야 하는 상황이라면 어떻게 해야할까요? 이 때 필요한 것이 actor입니다.

actor는 기본적으로 class와 거의 동일하다고 보시면 됩니다. 참조 타입으로 힙 영역에 저장되어 스레드끼리 공유할 수 있습니다. 다만 멀티스레딩 환경에서 Race Condition을 일으키지 않도록 하나의 스레드만 접근할 수 있도록 내부적으로 구현되어 있습니다. (또한, 상속을 지원하지 않습니다.)

즉, actor는 A 스레드가 actor에 접근하고 있다면 B 스레드가 actor에 접근하는 코드를 실행했을 때 그 코드를 기다리게할 수 있습니다.

Actor 구현

class나 struct를 구현하는 방식과 똑같습니다. class 자리에 actor로 구현해주면 되는 것이죠.

class RaceClass {
    var num = 0
    
    func increaseNum() {
        num += 1
    }
}

actor SomeActor {
    var num = 0
    
    func increaseNum() {
        num += 1
    }
}

Actor에 정의에 설명한 내용을 위 코드를 통해서 한번 더 설명해보도록 하겠습니다. class로 구현된 RaceClass의 경우 여러 스레드가 increaseNum를 동시에 실행할 수 있습니다. 그래서 Race Condition이 발생하는 것입니다. 하지만 actor로 구현한 SomeActor의 경우 하나의 스레드가 increaseNum를 실행하고 있다면 다음 스레드의 increaseNum 실행을 스위프트 자체 시스템이 기다리게 할 수 있습니다.

Actor-isolated

class와 동일하게 actor의 print문을 사용해서 property를 출력해보고 method를 실행해보도록 하겠습니다.

위와 같은 에러가 뜨는데요. Actor-isolated한 property와 method는 non-isolated context에서는 참조할 수 없다고 합니다.

위에서 actor는 스레드의 코드를 멈추게 할 수 있다고 했습니다. 따라서 property에 접근할 때, 그리고 method를 실행할 때 모두 저 코드들은 스레드에서 “기다려야”할 수도 있습니다. 따라서 앞에 await를 붙여서 실행하여야 합니다.

print(await someActor.num)
await someActor.increaseNum()

이렇게 실행하면 다른 스레드가 actor에 접근하고 있을 때는 기다리고 다른 스레드가 접근하지 않고 있을 때 위 코드가 실행됩니다.

Actor-isolated와 관련된 내용은 다음 포스팅에서 좀 더 자세하게 살펴보도록 하겠습니다.

profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.

0개의 댓글