Reentrant & Thread-safe

머핀조아·2023년 5월 24일
0
post-thumbnail

Reentrant

단일 스레드 환경에서 보통 사용하는 용어이다. 함수가 실행 도중에 중단될 수 있고, 동일한 스레드에서 동일한 함수를 다시 호출해도 안전하다면 재진입(reentrant) 가능하다고 할 수 있다.

재진입 함수의 조건

  1. 상수가 아닌 static 데이터를 포함해서는 안된다.
  2. 참조값을 상수가 아닌 static 데이터로 반환하면 안된다.
  3. 호출한 곳에서 가져온 데이터에 대해서만 동작해야 한다.
  4. Singleton resource에 대한 lock에 의존해서는 안된다.
  5. 자체 코드를 수정하지 않아야 한다. (고유 thread 저장소에서 실행하는 경우 제외)
  6. 재진입 불가한 program 혹은 routine을 호출하면 안된다.

Thread-safe

다중 스레드 환경에서 보통 사용되며, 여러 스레드가 동시에 동일한 함수를 실행할 수 있는 경우 thread-safe 하다고 할 수 있다. 표준 라이브러리에 있는 함수나 자료구조를 사용할 경우, 공식 문서에서 thread-safe 여부를 확인해서 사용해야 한다.


Example Code

// non-thread-safe & non-reentrant
var temp: Int
val notThreadSafeAndNotReentrant: (Int) -> Int = { input -> 
	temp = input
	temp + 10
}

// non-thread-safe & reentrant
val notThreadSafeAndReentrant: (Int) -> Int = { input ->
	temp = input
	input + 10
}

// thread-safe & non-reentrant
val threadSafeTemp: ThreadLocal<Int> = ThreadLocal()
val threadSafeAndNotReentrant: (Int) -> Int = { input ->
	threadSafeTemp.set(input)
	threadSafeTemp.get() + 10
}

// thread-safe & reentrant
val threadSafeAndReentrant: (Int) -> Int = { input -> input + 10 }

모든 함수를 thread-safe 하게 구현할 수 있지만, 그에 따른 성능 비용이 발생한다. Stack의 외부에서 memory에 접근해야 하는 한, 모든 함수를 reentrant 하게 만들 수는 없다. 따라서 best effort로 모든 함수에 대해 reentrant를 고려하며, 필요에 따른 thread-safe이 동반되어야 한다.

profile
채찍질이 필요한 개발자

0개의 댓글