티스토리 뷰

Swift/Concurrency

Actor (4) - Sendable

Zedd0202 2021. 10. 11. 21:15
반응형

 

안녕하세요 :) Zedd입니다.

오늘은 Sendable에 대해 공부!

 

# Actor

자 여러분 actor 아시죠!?

actor BankAccount { }

이렇게 actor 타입을 만들었었잖아요!

근데 Actor라는 것도 있어요. 얘는 뭘까요? 

Actor는 프로토콜이에요. 

모든 actor가 준수하고 있는 common protocol이 Actor입니다.

이 Actor 프로토콜은 모든 actor 타입을 일반화합니다.

actor 타입은 암시적으로 이 프로토콜(Actor)을 따르고 있어요.

actor BankAccount { }

let account = BankAccount()
account is Actor // true

 

이게 된다는거! 

🤷 : 이게 Sendable이랑 무슨..상관..

🧑‍💻 : Actor가 Sendable을 conform하고 있으니까!

protocol Actor : AnyObject, ✅ Sendable ✅

 

# Sendable

✔️ 프로토콜

문서 && Actor가 conform하고 있는것을 보면 추측할 수 있겠지만 요 Sendable은

Concurrency와 관련이 있는 프로토콜입니다.

 

[정의]

주어진 타입의 값이 concurrent code에서 안전하게 사용될 수 있음을 나타낸다.

동시에 사용하기에 안전한 타입 == Sendable

Actor간에 값을 공유할 수 있는 타입 == Sendable.

(A에서 B로 값을 복사하고, A와 B가 서로 간섭하지 않고 해당 값의 복사본을 안전하게 수정할 수 있는 경우 타입은 Sendable이 될 수 있음.)

 

자...Sendable은 아직은 잘 모르겠지만, 우리가 이제까지 공부했던 actor는 어느정도 아는 상태입니다.

actor는 shared mutable state에 대한 접근을 동기화하기 때문에 Concurrent code에서 data race를 피할 수 있었습니다.

"주어진 타입의 값이 concurrent code에서 안전하게 사용될 수 있음을 나타낸다."

즉, actor는 Sendable이죠.

 

Value type(ex. struct) 도 마찬가지입니다.

결국 Concurrent Code에서 Data race가 발생하는 원인은 데이터가 shared mutable state이기 때문.


이라고 했습니다.

즉, 데이터가 변경되지 않거나, 공유되지 않는 경우 data race는 발생할 수 없다는 것이죠. 

즉, Value type은 각 복사본이 독립적이기 때문에 Sendable이 될 수 있습니다. 

다만 Value type내의 모든 stored property가 모두 Sendable 타입인 경우에만 Sendable이 될 수 있습니다. 

struct BankAccount: Sendable {
    let accountNumber: Int
    var balance: Double
}

가능!

🤔 : Int, Double같은 type들..Sendable이야?

🧑‍💻 : ㅇㅇ. value-semantic types들은 모두 Sendable입니다. (여기 참고)

 

프로퍼티에 Sendable타입이 아닌 것들이 오면,

struct BankAccount: Sendable {
    let accountNumber: Int = 0
    let balance: Double = 0.0
    
    let zedd: Zedd // 🚨 Stored property 'zedd' of 'Sendable'-conforming struct 'BankAccount' has non-sendable type 'Zedd
}

class Zedd {}

컴파일 에러가 발생합니다.

하지만 Zedd class가 actor가 된다면?

struct BankAccount: Sendable {
    let accountNumber: Int = 0
    let balance: Double = 0.0
    
    let zedd: Zedd
}

actor Zedd {}

잘 됩니다. 왜냐? actor는 Actor프로토콜을 암시적으로 준수하고있고, Actor는 Sendable을 준수하고 있기 때문

(대충 actor는 Sendable이라는 소리) 

 


 

Class는 Sendable일까요?

1. Class는 모든 Subclass가 변경할 수 없는 데이터만 보유하는 경우 Sendable이 될 수 있습니다. 

2. Class가 내부적으로 동기화(ex. lock)을 수행하여 안전한 동시 접근을 보장하는 경우 Sendable이 될 수 있습니다.

하지만 보~~통 Class에 let만 있는것도 아니고..내부적으로 동기화 작업을 잘 하지도 않습니다.

즉, 대부분의 Class는 Sendable이 될 수 없습니다.

 

Class가 Sendable을 준수하게 하려면,

즉, 내가 Class를 사용하는데 concurrent code에서 안전하게 사용될 수 있음을 나타내고 싶다면

1. Class는 final이어야합니다. 

non-final class는 Sendable을 준수할 수 없습니다.

class BankAccount: Sendable {
    let accountNumber: Int = 0
    var balance: Double = 0.0
}
// 🚨 Non-final class 'BankAccount' cannot conform to `Sendable`

2. mutable stored property 없애기 

final class BankAccount: Sendable {
    let accountNumber: Int = 0
    var balance: Double = 0.0 // 🚨 Stored property 'balance' of 'Sendable'-conforming class 'BankAccount' is mutable
}

balance가 var로 mutable이기 때문에 Sendable을 준수할 수 없다고 에러가 납니다.

 

최종적으로

final class BankAccount: Sendable {
    let accountNumber: Int = 0
    let balance: Double = 0.0
}

이렇게 되어야 컴파일이 가능해집니다.

2. Class가 내부적으로 동기화(ex. lock)을 수행하여 안전한 동시 접근을 보장하는 경우 Sendable이 될 수 있습니다. 


이건 WWDC 에서 이렇게 말했는데..어떻게 해야 가능한거지?.. 

 

근데 사실 balance(잔액)의 경우 변경될 수 있으므로....

이럴때는 그냥 actor를 쓰고 var로 유지하는게 가장 베스트일듯..

 

# Function Type

다들 아시다시피 function,  closure는 참조타입입니다.

Sendable은 프로토콜이었고, 타입들은 자동으로 Sendable을 준수하거나 직접 준수하도록 해줄 수 있습니다.

하지만, Function type은 프로토콜을 준수할 수 없는 참조 타입이기도 합니다.

Swift에서 concurrency domains을 통해 함수를 전달할 수 있도록 하는 것은 중요하죠!

이를 위해 @Sendable Function type이 제안되었는데요.

의도와 맞게, @Sendable Function type은 concurrency domains간에 pass(전달)하는 것이 안전합니다.

(== 암시적으로 Sendable 프로토콜을 준수함)

 

사실 @Sendable이 나온 목적은 위와같은데.... 요 부분 잘 이해가 안가네요 ㅎ......

아무리봐도 그래서 뭐지..? 라는 느낌...... 누가 좀 알려주세요 ㅜㅜ...zzz

 

[참고]

https://github.com/apple/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md#new-sendable-attribute-for-functions

 

GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Lang

This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhance...

github.com

https://developer.apple.com/videos/play/wwdc2021/10133/

 

Protect mutable state with Swift actors - WWDC21 - Videos - Apple Developer

Data races occur when two separate threads concurrently access the same mutable state. They are trivial to construct, but are notoriously...

developer.apple.com

 

반응형