# Actor 정리 [Actor 개념 정리] - 동시성 코드간에 정보를 안전하게 공유할 수 있게 해주는 것 ㄴ 한 번에 하나의 작업만 변경 가능한 상태에 접근할 수 있도록 허용함 ㄴ 그렇기 때문에 Actor 내부에 있는 `변수(var)`에 접근하는 경우, `await`을 붙여줘야 함. 안 붙여주면 에러남 ㄴ 값이 변경될 일 없는 `상수(let)`는 `await` 안 붙여줘도 됨 - Actor 내부 프로퍼티는 다 actor-isolatied 프로퍼티 ㄴ Swift 는 Actor 내부의 코드만 Actor에 접근(write)할 수 있도록 보장함 ㄴ 이 보장을 actor isolation 이라고 함 ㄴ 그렇기 때문에 외부에서 Actor의 내부에 있는 프로퍼티 값을 변경하는 경우, 에러가 남 ㄴ 만약 Actor 내부에 있는 프로퍼티가 클래스 타입이라면, 클래스 타입안에 있는 프로퍼티 값 변경에 대해서는 actor isolation이 아님 - actor는 다른 스레드가 쓰기를 하는 동안 한 스레드가 변경 가능한 객체에 액세스할 때 발생할 때 생기는 문제를 해결해줄 수 있음 [발표 중 나온 의문들] - `isolated`이 무엇인가? - `actor` 가 다른 독립된 스레드에서 실행되는가? - `actor` 내부가 어떤 스레드에서 실행되는가? - `actor`가 어떤 원리로 돌아가고 `await async` 랑 어떤 연관이 있는가? - `Race Condition` 과 `Data Race`이 무엇이고, `actor`는 어떤 것과 더 관련이 있는가 - `actor`는 데이터 레이스에 초점을 맞춰하는가? - 데이터 레이스에 초점을 맞춘다는 것이 디스패치 큐하고 비교하면서 한다는 것인가? [참고 사이트] - https://zeddios.tistory.com/1303 - https://zeddios.tistory.com/1304 - https://developer.apple.com/videos/play/wwdc2021/10133 - https://swiftsenpai.com/swift/actor-prevent-data-race/ - https://www.avanderlee.com/swift/race-condition-vs-data-race/ [예시 코드] - 회의 시간에 테스트 해본 코드 ```swift actor SomeActor { let str: String var numbers: [Int] private(set) var number: Int // SomeClass 타입 let someClass1 = SomeClass(a: 0) var someClass2 = SomeClass(a: 1) // Int 타입 let someA1 = SomeClass(a: 2).a var someA2 = SomeClass(a: 3).a // SomeStruct 타입 let someStruct1 = SomeStruct(b: 4) var someStruct2 = SomeStruct(b: 5) // Int 타입 let someB1 = SomeStruct(b: 6).b var someB2 = SomeStruct(b: 7).b init(str: String, number: Int) { self.str = str self.numbers = [number] self.number = number } func change(number: Int) { self.number = number } } class SomeClass { var a: Int init(a: Int ) { self.a = a } } struct SomeStruct { var b: Int init(b: Int ) { self.b = b } } let someActor = SomeActor(str: "하이엑터", number: 1228) // let은 await 안 붙여줘도 됨 print(someActor.str) // var는 await 붙여줘야 함 // print(someActor.numbers) // Error // print(someActor.number) // Error print(await someActor.numbers) print(await someActor.number) // actor 내부에 참조타입 프로퍼티가 있으면, 참조타입의 값에 대해서는 변경 가능 // 참조타입의 값(a,b)이 변해도 actor 내부에 있는 프로퍼티(someClass1, someClass2)가 갖고 있는 주소값에 대해서는 변화가 없으므로 참조타입 내부 프로퍼티 값은 변경가능 someActor.someClass1.a = -1 print(someActor.someClass1.a) await someActor.someClass2.a = -2 print(await someActor.someClass2.a) // Struct는 값 타입이므로 let이면 변경 불가 // someActor.someStruct1.b = -3 // Error // var여도 actor 내부 프로퍼티는 isolated property 이므로 직접 변경 불가 // someActor.someStruct2.b = -3 // Error // actor 내부 프로퍼티를 변경하려면 내부 로직에 의해만 가능함 await someActor.change(number: 100) ``` - Language guide에 소개된 코드 ```swift actor TemperatureLogger { let label: String var measurements: [Int] private(set) var max: Int init(label: String, measurement: Int) { self.label = label self.measurements = [measurement] self.max = measurement } } let logger = TemperatureLogger(label: "Outdoors", measurement: 25) print(await logger.max) print(logger.max) ``` - wwdc에 소개 된 코드 ```swift actor Counter { var value = 0 func increment() -> Int { value = value + 1 return value } } let counter = Counter() Task.detached { print(await counter.increment()) // 1, 2 } Task.detached { print(await counter.increment()) // 2, 1 } ```