interlocked 계열 함수로 보호되는 변수를 참조하기 Programming

interlocked 계열 함수(InterlockedIncrement, interlockeddecrement, interlockedexchange...)를 사용하면 Lock를 사용하지 않고도 스레드간 변수 공유가 가능하기 때문에 성능을 높이기 위해 많이 사용됩니다. 해당 변수를 변경하는 동작(write)은 interlocked 함수를 사용하여 수행하게 되는데, 참조만 하는 동작(read)은 직접 참조를 해도 될까요?

ACE에서도 interlocked 함수처럼 변수의 atomic operation를 보장해주는 클래스가 있습니다. ACE_Atomic_Op<> 가 그것인데, 사용하는 방법은 아래와 같습니다.
ACE_Atomic_Op<ACE_Thread_Mutex, long> var = 0;
var = 1;
++
var;
if ( 0 == var.value() )
{
}


ACE_Atomic_Op의 소스를 보니(atomic_op.inl) 해당 변수를 write하는 경우에만 interlocked 함수를 사용하고 read만 하는 경우에는 직접 참조를 하더군요.
ACE_INLINE ACE_Atomic_Op<ACE_Thread_Mutex, long> &
ACE_Atomic_Op<ACE_Thread_Mutex, long>::operator= (long rhs)
{
#if defined (WIN32)
  ::InterlockedExchange (const_cast<long *> (&this->value_), rhs);
#else /* WIN32 */
  (*exchange_fn_) (&this->value_, rhs);
#endif /* WIN32 */
  return *this;
}

ACE_INLINE long
ACE_Atomic_Op<ACE_Thread_Mutex, long>::value (void) const
{
  return this->value_;
}


결론은
write하는 동작은 interlocked 계열 함수를 사용하고 read만 하는 동작은 직접 참조해도 됩니다.

ACE_Atomic_Op<> 를 사용하실때 주의하실 점이 있는데, 자료형을 반드시 long으로 지정하셔야 interlock 함수를 사용하게 됩니다. int나 bool 등의 다른 타입으로 지정하시면 그냥 lock걸고 변수를 사용하게 됩니다. 이 경우는 read도 lock를 걸고 사용하더군요.
ACE_Atomic_Op<ACE_Thread_Mutex, int> var; // with lock
ACE_Atomic_Op<ACE_Thread_Mutex, bool> var; // with lock
ACE_Atomic_Op<ACE_Thread_Mutex, long> var; // interlocked



덧글

댓글 입력 영역