
그렇다면 Actor내의 모든 코드는 thread safe 할까?
actor CurrentUserManager {
func updateDatabase(userInfo: MyUserInfo) {
// 여러 thread에서 userInfo를 참조하게 되는 코드
// 이 경우 actor 내에서도 data race가 발생할 수 있다.
}
}
class MyUserInfo {
var name: String
}
→ Data race가 발생하게 된다! Sendable Protocol을 사용하자Value type
value type의 경우 concurrency에서 값의 복사가 이루어지기 때문에 data race가 발생하지 않으므로, 기본적로 Sendable이다. 따라서, 옆에 그냥 붙여주면 된다.
struct MyUserInfo: Sendable {
let name: String
}
다만, struct 내의 모든 구성이 value type이거나, sendable을 준수해야 한다.
다음의 경우에는 Sendable을 붙일 수 없다.
struct MyUserInfo: ~~Sendable~~ {
let name: String
var myClass: MyClass // NOT Sendable
}
Reference type (Class)
class의 경우 sendable을 사용하려면
var가 없어야 한다.final이어야 한다.final class MyClassUserInfo: Sendable {
let name: String
init(name: String) {
self.name = name
}
}
굳이 var를 사용하고 싶다면, @unchecked 키워드를 통해 컴파일러를 무시하고 Sendable 하게 구현할 수 있다.
대신, 이 경우에는 손수 actor를 구현했던 것처럼 직접 lock을 만들어서 thread safty를 보장해야 한다.
→ 매우 추천하지 않는다.
final class MyClassUserInfo: @unchecked Sendable {
private var name: String
let lock = DispatchQueue(label: "com.MyApp.MyClassUSerInfo")
init(name: String) {
self.name = name
}
func updateName(name: String) {
queue.async {
self.name = name
}
}
}
https://www.youtube.com/watch?v=wSmTbtOwgbE&list=PLwvDm4Vfkdphr2Dl4sY4rS9PLzPdyi8PM&index=12