코 루틴을 사용한 Kotlin / 네이티브 멀티 스레딩
나는 kotlin 멀티 플랫폼을 시도해 왔고 훌륭하지만 스레딩은 나를 괴롭힌다. 스레드 간의 상태 고정은 개념적으로 의미가 있으며 작은 개체 또는 기본 요소가 앞뒤로 전달되는 간단한 예제에서는 잘 작동하지만 실제 응용 프로그램에서는 InvalidMutabilityException을 피할 수 없습니다.
Android 앱에서 다음 공통 코드 스 니펫을 가져옵니다.
class MainViewModel(
private val objectWhichContainsNetworking: ObjectWhichContainsNetworking
)
private var coreroutineSupervisor = SupervisorJob()
private var coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Main + coreroutineSupervisor)
private fun loadResults() {
// Here: Show loading
coroutineScope.launch {
try {
val result = withContext(Dispatchers.Default) { objectWhichContainsNetworking.fetchData() }
// Here: Hide loading and show results
} catch (e: Exception) {
// Here: Hide loading and show error
}
}
}
매우 복잡한 것은 아니지만 공통 코드에서 사용하고 Kotlin / Native에서 실행하는 경우 MainViewModel에 InvalidMutabilityException을 발생시킵니다.
그 이유는 withContext에 전달 된 모든 것이 재귀 적으로 고정되어 있으므로 objectWhichContainsNetworking이 MainViewModel의 속성이고 withContext에서 사용되기 때문에 MainViewModel이 고정에 걸리기 때문인 것 같습니다.
제 질문은 이것이 현재 Kotlin / Native 메모리 모델의 한계 일 뿐입니 까? 아니면 현재 버전의 코 루틴일까요? 그리고 이것에 대해 어떤 방법이 있습니까?
참고 : 코 루틴 버전 : 1.3.9-native-mt. kotlin 버전 1.4.0.
편집 1 : 그래서 위의 슬림 다운 코드가 실제로 잘 작동하는 것 같습니다. 유죄 코드는 뷰 모델 (마지막 뷰 상태에 대한 참조를 유지하는 데 사용됨)에서 업데이트 가능한 변수였으며, 고정 된 다음 변경하려고 할 때 예외를 throw합니다. 흐름 / 채널을 사용하여 var 참조가 필요하지 않은지 확인하고 이것이 전체 문제를 해결하는지 확인하려고합니다.
참고 : 처음에 MainViewModel이 동결되는 것을 방지하는 방법이 있다면 여전히 환상적 일 것입니다!
편집 2 : var를 Flow로 대체했습니다. 여기 헬퍼를 사용할 때까지 iOS에서 표준 흐름 수집을 얻을 수 없습니다.https://github.com/JetBrains/kotlinconf-app/blob/master/common/src/mobileMain/kotlin/org/jetbrains/kotlinconf/FlowUtils.kt.
MainViewModel은 여전히 고정되지만 모든 상태가 변경 불가능하므로 더 이상 문제가되지 않습니다. 누군가에게 도움이되기를 바랍니다!
답변
원래 코드에서 부모 개체의 필드를 참조하므로 전체 부모를 캡처하고 고정하게됩니다. 코 루틴의 문제가 아닙니다. 코 루틴은 Kotlin / Native의 다른 모든 동시성 라이브러리와 동일한 규칙을 따릅니다. 스레드를 교차 할 때 람다를 고정합니다.
class MainViewModel(
private val objectWhichContainsNetworking: ObjectWhichContainsNetworking
)
//yada yada
private fun loadResults() {
coroutineScope.launch {
try {
val result = withContext(Dispatchers.Default) {
//The reference to objectWhichContainsNetworking is a field ref and captures the whole view model
objectWhichContainsNetworking.fetchData()
}
} catch (e: Exception) {}
}
}
이런 일이 발생하지 않도록하려면 :
class MainViewModel(
private val objectWhichContainsNetworking: ObjectWhichContainsNetworking
){
init{
ensureNeverFrozen()
}
//Etc
메모리 모델에서 가장 복잡한 것은 이것입니다. 캡처되는 것에 익숙해지고 그것을 피합니다. 익숙해지면 그렇게 어렵지는 않지만 기본을 배워야합니다.
나는 이것에 대해 길게 이야기했습니다.
실용적인 Kotlin / 네이티브 동시성
Kotlin 네이티브 동시성 실습
KotlinConf KN 동시성
기억 모델은 변하고 있지만, 그것이 도착하기까지는 꽤 오래 걸릴 것입니다. 메모리 모델에 익숙해지면 일반적으로 변경 불가능한 문제를 진단하기가 쉽습니다.