728x90

volatile

컴파일러에게 최적화를 하지 말아달라는 요청 키워드(C#, Java와 같이 캐시, 메모리베리어 와 같은 기능은 없다.)

volatile int a = 3;
 

SpinLock 정책 (무한 대기)

제일 먼저 접근한 스레드가 lock을 걸고 다른 스레드는 대기하면서 계속해서 lock이 아직 걸려있는지 아닌지를 확인한다. 단순하게 구현이 가능하고 이해하기 쉽지만 대기하는 스레드가 많아질 경우 쓸데없이 CPU를 낭비하게 될 수도 있다는 단점이 있다.

class SpinLock
{
public:
	void lock()
	{
        // CAS(Compare And Swap)
		bool expected = false;
		bool desired = true;
		while (_lock.compare_exchange_strong(expected, desired) == false)
		{
			expected = false;
		}
	}

	void unlock()
	{
		_lock.store(false);
	}

private:
	atomic<bool> _lock = false;
};
 

lock을 걸지 않았을 때 상태를 false로 두고 lock을 걸면 true로 바꾸어 다른 스레드가 접근할 수 없도록 해주었다.

여기서 주의할 점은 compare_exchange_strong함수인데, 이 함수의 의사코드는 다음과 같다.

if (_lock == expected)
{
	expected = _lock;
	_lock = desired;
	return true;
}
else
{
	expected = _lock;
	return false;
}
 

위의 과정을 한 번에 처리해주지 않으면 멀티스레드 환경에서 lock을 제대로 걸어줄 수 없으며, atomic에서 제공하는 함수이다. _lock과 expected가 같지 않으면 expected를 현재 _lock의 값으로 변경하기 때문에 이 부분을 유의해야 한다.

sleep, yield

운영체제로부터 스레드를 실행하기 위해 넘겨받은 time slice를 포기하거나, 양보하면서 무한 대기가 아니라 필요한 것 우선, 또는 현재 작업 미루기를 할 때 사용할 수 있다.

this_thread::sleep_for(0ms);
this_thread::yield();
 

 

 

728x90

'C++ > 멀티스레드' 카테고리의 다른 글

Condition Variable  (1) 2023.05.14
Event  (0) 2023.05.14
DeadLock  (0) 2023.05.14
Lock  (0) 2023.05.12
atomic  (0) 2023.05.12

+ Recent posts