• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    미해결

안녕하세요. 람다에서 외부변수를 사용하는 Closure관련해 궁금해 질문드려요.

23.03.07 00:44 작성 23.03.07 00:48 수정 조회수 357

2

안녕하세요. 먼저 질좋은 강의 만들어주시고 제공해주셔서 감사드려요!
강의중 Closure가 자바와 다르게 final이 아닌 var변수를 람다안에서 값을 변경가능한것까지 이해하였습니다.
다른 궁금증이 하나 생겨서요.
Closure가 람다를 진입하기전 변수를 포획해서 진행한다고 하셨는데, 이는 동시성 문제로부터 자유롭나요?

답변 1

답변을 작성해보세요.

2

안녕하세요, 클래식님!! 정말 좋은 질문 주셔서 감사드립니다!! 🙏🙏

결론부터 말씀드리자면 thread-safe하지 않습니다! 즉, 동시성 문제를 고려해야만 합니다.

 

https://medium.com/@yangweigbh/how-kotlin-lambda-capture-variable-ef90e11e531d

에서 Kotlin이 변수를 capture 하는 방식을 확인해보실 수 있는데요! 간략히 말씀드리면 어떤 변수를 Object로 만든 다음, 그 Object의 reference를 각 람다가 공유하는 방식입니다.

 

실제로 코루틴을 활용해 한 변수에 여러 스레드가 동시에 접근하게 하면 의도하지 않은 동작을 확인할 수 있습니다.

@Test
fun lambdaClosureMultiThreadTest(): Unit = runBlocking {
  // given
  val dispatcher = Executors.newFixedThreadPool(50).asCoroutineDispatcher()
  var count = 0 // 람다 밖에 가변 변수를 하나 만든다.
  
  // when
  val jobs = (1..1000).map { // (50개 스레드 풀에서) 동시에 count를 1씩 총 1,000번 더한다.
    launch(dispatcher) {
      count += 1
    }
  }
  jobs.joinAll()
  
  // then
  assertThat(count).isEqualTo(1000)
}

위의 코드는 50개 스레드 풀에서 1000개의 코루틴이 하나의 변수 count 에 접근해 1을 더하는 테스트 코드입니다! 이 테스트 코드는 높은 확률로 실패하는데요!!! (제 컴퓨터에서는 998이나 999가 자주 나오더라고요...) 바꿔 말하면 한 변수에 한 thread만 접근할 수 있는 것이 아니라 여러 thread가 동시에 접근할 수 있다는 의미입니다.

 

혹시나 궁금한 점이 더 있으시다면 편하게 질문 부탁드리겠습니다.

감사합니다. 오늘도 행복한 하루 되세요!! 🙏