[Android] coroutine Mutex 왜써요?
지난번에 coroutine mutex에 대해 다뤘습니다.
이번엔 제가 실제로 mutex를 이용해서 동시성 문제를 해결한 예시를
보여드리겠습니다.
모든 코드는 비슷한 상황 재현을 위해 ChatGPT로 만든 임시 코드입니다.
구현은 완전히 다르며 순수히 예시를 위한 코드입니다.
data class DummyFile(
val path: String,
val subItems: MutableList<DummyFile> = mutableListOf()
)
fun create(file: File) =
DummyFile(
path = file.path,
subItems = mutableListOf()
)
해당 데이터 클래스를 이용해서
선택한 파일의 하위 아이템을 전부 subitem에 넣어줘야합니다.
fun createDummyFile(file: File): DummyFile {
if (file.isFile) {
return DummyFile(file.name)
} else {
//해당 파일이 폴더일떄
val dummyFile = DummyFile(file.name)
val subItems = file.listFiles()
if (subItems != null) {
//폴더의 아이템들 전부
for (subItem in subItems) {
//하위 요소를 다시 탐색한다
val subDummyFile = createDummyFile(subItem)
//탐색한 하위요소를 현재 파일의 하위요소에 더해준다
dummyFile.subItems.add(subDummyFile)
}
}
return dummyFile
}
}
이 함수를 이용해서 선택한 파일의 하위 요소를 전부 뽑아서
데이터를 보내줬습니다.
하지만 여기서 문제가 생겼습니다!
파일이나 폴더가 많지 않은 테스트용 폰에서는 순식간에 됐지만
파일이 굉장히 많고 폴더 구조가 복잡한 제 폰에서는 타임 아웃에 걸려
데이터를 보내지 못하는 이슈가 생겨습니다!
이를 해결하기위해 저는 코루틴을 이용해 재귀하는 부분을 비동기로 처리했습니다.
for (subItem in subItems) {
CoroutineScope(Dispatchers.IO).launch{
val subDummyFile = createDummyFile(subItem)
dummyFile.subItems.add(subDummyFile)
}
}
이렇게 하면 탐색하는 부분이 비동기적으로 동작하여
정말 빠르게 파일 트리를 탐색하는 것이 가능해졌습니다.
하지만!! 또 문제가 생겼습니다.
같은 자원을 동시에 수정하는 상황이다 보니 에러가 발생하더군요.
같은 자원을 같이 사용하면 안된다? 벌써 부터 감이 오시죠?
어느자원을 같이 사용했나 보니까
dummyFile.subItems.add(subDummyFile)
해당 부분을 여러코루틴에서 동시에 접근하여 리스트에 add를 하니 발생하는 거였습니다.
그럼 해당 부분을 동시에 수정 못하게 하면 되겠네요?? Mutex!!
private val mutex = Mutex()
...
for (subItem in subItems) {
CoroutineScope(Dispatchers.IO).launch{
val subDummyFile = createDummyFile(subItem)
mutex.withLock{ dummyFile.subItems.add(subDummyFile) }
}
}
이렇게 한번에 여러 곳에서 수정이 불가능하게 되었습니다.
이렇게 해서 파일트리 탐색 모듈 개발중 일어난 동시성 문제를 해결하였습니다.
비동기 처리를 하다보면 이렇게 순식간에 많은 코루틴에서 한 자원에 접근하는 일이
빈번하게 일어나게 됩니다.
이런 동시성 문제를 해결하는 방법을 알고 있다면 능숙하게 대처 할 수 있겠죠?
감사합니다!