Reordering

void foo()
{
	a = b + 1;
	b = 1;
}

Untitled

Reordering 해결법

void foo()
{
	a = b + 1;
	// 메모리에 fence를 치는 어셈 명령어를 준다. (원시적 방법)
	// __asm { mfence }
	std::atomic_thread_fence( std::memory_order_release );
	b = 1;
}

Memory Order

std::atomic<int> x = 0;
std::atomic<int> y = 0;

void foo()
{
	int n1 = y.load(std::memory_order_relaxed);
	x.store(n1, std::memory_order_relaxed);
}

void goo()
{
	int n2 = x.load(std::memory_order_relaxed);
	y.store(100, std::memory_order_relaxed);
}

std::memory_order_relaxed
- 오버헤드가 가장 적다.
- atomic operation 만 보장.
- 실행순서는 변경될 수 있다. (아래 두 코드의 실행 순서가 변할 수 있다)
// int n1 = y.load(std::memory_order_relaxed);
// x.store(n1, std::memory_order_relaxed);
void foo()
{
	a.store(100, std::memory_order_relaxed);
	b.store(1, std::memory_order_release);
**}

void goo()
{
	if (flag.load(std::memory_order_acquire) > 0)
	{
		// Acquire 이후에 아래 값을 읽는것은 보장한다.
		assert(a.load(std::memory_order_relaxed) == 100);
	}
}

std::memory_order_release, std::memory_order_acquire
- release 이전의 코드는 acquire 이후에 읽을 수 있다는 것을 보장.**
void main()
{
	a.store(100, std::memory_order_seq_cst);
	b.store(200, std::memory_order_seq_cst);
	c.store(300); // 디폴트 옵션이 std::memory_order_seq_cst
}

std::memory_order_seq_cst
- 원자 연산과 순서를 보장한다.
	- 해당 옵션이 있는 애들끼리는 순서를 보장.
- 오버헤드가 가장 크다.