
๋ค์ด๊ฐ๋ฉฐ
๋์์ฑ ํ๋ก๊ทธ๋๋ฐ์ ์งํํ๋ฉด์ ๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ ๋ฐ์ดํฐ ๋๊ธฐํ์ ๋๋ค. ์ค๋ ๋๊ฐ ๊ฒฝํฉ(race-condition)์ด ๋ฒ์ด์ก์ ๋, ๊ณต์ ์์์ ๋ํ ๋๊ธฐํ๋ฅผ ์งํํ๊ธฐ ์ํด ๋ํ์ ์ผ๋ก Mutex Lock์ ์ฌ์ฉํฉ๋๋ค. ๊ณ ์ฑ๋ฅ ํ๋ก๊ทธ๋๋ฐ์์ Lock์ ์ ๋์ ์ด๋ผ๊ณ ์๊ฐํ์๋ฉด ๋ ๊ฒ ๊ฐ์ต๋๋ค. ํ์ง๋ง ๋ฐ์ดํฐ ๋๊ธฐํ์ ๋ํ ๋ฌธ์ ๊ฐ ์์ง ๋จ์์๊ธฐ ๋๋ฌธ์ Lock์ ์ต์ํํ๋ฉด์ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ์ค๋์ Lock์ ์ฌ์ฉํ์ง ์์ ๋ฝํ๋ฆฌํ(Lock-Free Queue)์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
Producer and Consumer

๋์์ฑ์ ์ฒ๋ฆฌํ๋ ์ ํต์ ์ธ ๋ฐฉ์์ธ ์์ฐ์-์๋น์ ํจํด(Producer Consumer Pattern)์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฒคํธ/์ด์๊ฐ ๋ฐ์ํ๋ฉด ์์ฐ์ ์ค๋ ๋์์ Queue์ Job์ Pushํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ Consumer ์ค๋ ๋์์ Job์ Popํด์ ์ฒ๋ฆฌํฉ๋๋ค. ์์ฐ์๋ ๋์์์ด Job์ Queue์ ๋ฃ๊ณ ์๋น์๋ ๋์์์ด Job์ Queue์์ ๋บ๋๋ค. ๋ง์ฝ ์๋น์๊ฐ Job์ ์ฒ๋ฆฌํ๋ ์๋๋ณด๋ค ์์ฐ์๊ฐ Job์ Pushํ๋ ์๋๊ฐ ๋ ๋น ๋ฅธ ๊ฒฝ์ฐ์๋ ๋ณ๋ชฉ์ด ์ผ์ด๋ ์ ์์ต๋๋ค. ๊ทธ๋์ ์ฌ๋ฌ ์๋น์ ์ค๋ ๋๋ฅผ ์ค๋ ๋ ํ๋ก ์ฒ๋ฆฌํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.

์ด ๊ตฌ์กฐ์์ ๊ณต์ ์์(Shared Resource)์ Queue์ ๋๋ค. ์์ฐ์๊ฐ pushํ๋ ๋์ ์๋น์๋ pop์ ๋ชป ํ๊ณ , ์๋น์๊ฐ popํ๋ ๋์ ์์ฐ์๋ push๋ฅผ ๋ชป ํฉ๋๋ค. ์ฌ๋ฌ ์ค๋ ๋๋ค์ด ๊ณต์ ์์์ ๋๊ณ ๊ฒฝํฉ์ ๋ฒ์ด๋ ๋์ Busy-waiting์ด ๋ฐ์ํ๊ณ Context Switching์ด ๋ฐ์ํฉ๋๋ค. ๋ฌผ๋ก ์ ๋ง ๋ฆฌ์ผํ์์ด ์๋๋ผ 100ms~1000ms ์ ๋์ ๋๋ ์ด๊ฐ ํ์ฉ๋๋ค๋ฉด ์์ฐ์-์๋น์ ํจํด๋ ๋์์ง ์์ ์ ํ์ ๋๋ค. ์ฝ๋ ๋ณต์ก์ฑ๊ณผ CPU ๊ฐ์ฉ๋ฅ ์ธก๋ฉด์์ ์ ๋ฆฌํ ๋ถ๋ถ์ด ์์ต๋๋ค. SPSC/MPSC๊ตฌ์กฐ(Single Consumer)์์๋ Lock์ด ํ์ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ด ํจํด์ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ณ ์ฑ๋ฅ ํ๋ก๊ทธ๋๋ฐ์์๋ Lock Free๋ฅผ ์งํฅํ๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์ ๋์ฑ ๋ฐ์ ๋ ํํ์ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
CAS(Compare and Swap)
Compare and Swap(CAS, ๋น๊ต ํ ๊ตํ)์ ๋์์ฑ ์ ์ด๋ฅผ ์ํ ํต์ฌ ์์์ ์ฐ์ฐ์ ๋๋ค. ๋ฝ์ ์ฐ์ง ์๊ณ ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ์์ ํ๊ฒ ๋ฐ์ดํฐ๋ฅผ ๊ฐฑ์ ํ ์ ์๊ฒ ํด์ฃผ๋ ๊ธฐ๋ณธ ๋น๋ฉ ๋ธ๋ก์ ๋๋ค. ๋ฉํฐ ์ค๋ ๋, ๋ฉํฐ ์ฝ์ด ํ๊ฒฝ์์ ๊ฐ ๋ณ์๋ ์ค๋ ๋ ๋ด์ ์คํ(์บ์)์ ์ ์ฅ๋ฉ๋๋ค. ์ด ๋ณ์์ ๋ํด์ ์ค๋ ๋์ ์ ์ฅ๋ ๊ฐ๊ณผ ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋ ๊ฐ์ ๋น๊ตํ์ฌ ๊ฐ์ด ๊ฐ๋ค๋ฉด ์๋ก์ด ๊ฐ์ผ๋ก ์นํํด์ค๋๋ค. ๊ฐ์ด ๋ค๋ฅด๋ฉด ๊ณ์ ์ฌ์๋๋ฅผ ํฉ๋๋ค.
๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋ ๊ฐ๊ณผ CPU ์บ์์ ์ ์ฅ๋ ๊ฐ์ด ๋ค๋ฅธ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ ์ด๋ฅผ ๊ฐ์์ฑ ๋ฌธ์ ๋ผ๊ณ ํฉ๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ๊ฒ์ด CAS ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค. ํ๋์จ์ด ์์ ์ธก๋ฉด์์ ์ค๋ ๋๊ฐ ์ถฉ๋์ด ๋ฐ์ํ์ ๋ ์ด๋ฅผ ์์์ฑ์ผ๋ก ๋ณด์ฅํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋๋ค. ์ค๋ ๋ ๊ฒฝํฉ์ ์ต์ ๊ฐ์ ์ ์งํ๋ ๋ฐฉ์์ ๋๋ค.
CAS๋ ์ธ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๊ณ ๋์ํฉ๋๋ค.
1. ๋ฉ๋ชจ๋ฆฌ ์ฃผ์ (addr): ๋ฐ๊ฟ ๊ฐ์ด ์ ์ฅ๋ ์์น
2. ์์ ๊ฐ (expected): ์ฐ๋ฆฌ๊ฐ ์์ํ๋ ํ์ฌ ๊ฐ
3. ์ ๊ฐ (desired): ๋ฐ๊พธ๊ณ ์ถ์ ๊ฐ
if (*addr == expected) {
*addr = desired;
return true; // ์ฑ๊ณต
} else {
expected = *addr; // ์คํจ ์ ์์ ๊ฐ ๊ฐฑ์
return false;
}
์ฆ, ๋ด๊ฐ ๋ฐ๊พธ๋ ค๊ณ ํ๋ ๊ฐ์ด ์์ํ ๊ทธ๋๋ก๋ผ๋ฉด ๋ฐ๊ฟ์น๊ธฐ(์ฑ๊ณต, ์งํ)ํ๊ณ , ์๋๋ฉด ์์ ๊ฐ์ ๊ฐฑ์ (์คํจ, ์ฌ์๋)ํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
std::atomic<int> x{10};
int expected = 10;
int desired = 20;
if (x.compare_exchange_weak(expected, desired)) {
// x == 20 ์ผ๋ก ์ฑ๊ณต์ ์ผ๋ก ๊ต์ฒด๋จ
} else {
// ์คํจ, expected์๋ x์ ์ค์ ๊ฐ์ด ๋ค์ด์์
}

CAS ์๊ณ ๋ฆฌ์ฆ์ ์ฅ์ ์ ์ฑ๋ฅ ๊ทธ์์ฒด์ ๋๋ค. ๋์ ์ฑ๋ฅ์ ๋์์ฑ ์๋ฃ๊ตฌ์กฐ๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค. ์ค๋ ๋ ๊ฐ ์ถฉ๋์ด ์์ด๋ ์ ์ฒด ์์คํ ์ด ๋ฉ์ถ์ง ์๊ณ ๊ณ์ ์งํํ ์ ์์ต๋๋ค.

๋ ์ค๋ ๋ ๋ชจ๋ ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ์์ ๊ฐ 3์ ์ฝ์ต๋๋ค. Thread 2๊ฐ ์ฑ๊ณต(๋ น์)ํ์ฌ ๋ณ์๋ฅผ 8๋ก ์ ๋ฐ์ดํธํฉ๋๋ค. Thread 1์ ์ฒซ ๋ฒ์งธ CAS๋ ๊ฐ์ด ์ฌ์ ํ 3์ด๊ธฐ๋ฅผ ๊ธฐ๋ํ๋ฏ๋ก, CAS๋ ์คํจ(๋นจ๊ฐ์)ํฉ๋๋ค. ๋ฐ๋ผ์ Thread 1์ ๊ฐ์ ๋ค์ ์ฝ๊ณ , ๋ ๋ฒ์งธ CAS๋ ์ฑ๊ณตํฉ๋๋ค. ์ฌ๊ธฐ์ ์ค์ํ ์ ์ CAS๊ฐ ์๋ฃ๊ตฌ์กฐ์ ๋ฝ์ ํ๋ํ์ง ์๊ณ , ์ ๋ฐ์ดํธ๊ฐ ์ฑ๊ณตํ๋ฉด 'true'๋ฅผ ๋ฐํํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด 'false'๋ฅผ ๋ฐํํ๋ค๋ ๊ฒ์ ๋๋ค.
๋จ์ ์ ABA๋ฌธ์ ์ Busy-wait์ด ์์ต๋๋ค. ABA๋ ๊ฐ์ด A -> B -> A๋ก ๋ณํ๋ฉด CAS๋ "์ ๋ฐ๋์๋ค"๊ณ ์ฐฉ๊ฐํ๊ฒ ๋ฉ๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฒ์ ๋ฒํธ๋ฅผ ๋ถ์ด๊ฑฐ๋ ๋ณ๋์ Pointer๋ฅผ ๋ฌ์์ฃผ๊ธฐ๋ ํฉ๋๋ค. ๋ํ ์ค๋ ๋๊ฐ ๊ฒฝํฉ์ด ์ฌํด์ง ๊ฒฝ์ฐ CAS๊ฐ ๊ณ์ ์คํจํ๋๋ฐ ์ด๋ CPU๋ญ๋น๋ก ์ด์ด์ง๋๋ค. ๊ฒฝ์ ์ํ์์ ๋ฝํ๋ฆฌ๋ CPU๋ฅผ ํ์์ ๊ธฐ๋ค๋ฆฌ๊ณ ๋ฎคํ ์ค๋ OSํํ ๋งก๊ธฐ๊ณ ์ ๋ญ๋๋ค. "CPU ๋ถํ๊ฐ ๋๋๋ผ๋ Sleep๋ณด๋ค๋ ์ข์ง ์์๊น"๋ผ๊ณ ์๊ฐ๋๋ ๋ถ๋ถ์ ๋๋ค.
Lock-Free queue ์์
๋ณดํธ์ ์ผ๋ก ์ฌ์ฉ๋๋ Michael-Scott lock-free queue๋ฅผ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค. AI๊ฐ ์ ๋ฆฌํ ๋ด์ฉ์ ํ ๋๋ก ์ดํด๋ณด๊ฒ ์ต๋๋ค.
// lock_free_queue_ms.hpp
#pragma once
#include <atomic>
#include <memory>
#include <optional>
// Michael-Scott lock-free queue (๊ต์ก/์ค์ต์ฉ ๊ตฌํ)
// ์ฃผ์: ์์ฐ ํ๊ฒฝ์์๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฌ์ฉ/ํ์(ABA ๋ฐฉ์ง)๋ฅผ ์ํ ์ถ๊ฐ ๊ธฐ๋ฒ ํ์.
// - ๊ถ์ฅ: Hazard pointers, Epoch-based reclamation, or use a well-tested library (boost::lockfree, folly).
template<typename T>
class LockFreeQueue {
private:
struct Node {
std::shared_ptr<T> data; // shared_ptr๋ก ๋ฐ์ดํฐ ์๋ช
๊ด๋ฆฌ
std::atomic<Node*> next;
Node() : data(nullptr), next(nullptr) {}
explicit Node(T const& value) : data(std::make_shared<T>(value)), next(nullptr) {}
};
std::atomic<Node*> head;
std::atomic<Node*> tail;
public:
LockFreeQueue() {
// ๋๋ฏธ ๋
ธ๋๋ก ์ด๊ธฐํ (MS ์๊ณ ๋ฆฌ์ฆ์ ํ์ค)
Node* dummy = new Node();
head.store(dummy, std::memory_order_relaxed);
tail.store(dummy, std::memory_order_relaxed);
}
~LockFreeQueue() {
// ๋จ์ ์๋ ๋
ธ๋๋ค ํด์
while (Node* old = head.load(std::memory_order_relaxed)) {
head.store(old->next.load(std::memory_order_relaxed), std::memory_order_relaxed);
delete old;
}
}
// enqueue: ๋์ ๋
ธ๋ ์ถ๊ฐ
void enqueue(T const& value) {
Node* newNode = new Node(value);
while (true) {
Node* last = tail.load(std::memory_order_acquire);
Node* next = last->next.load(std::memory_order_acquire);
if (last == tail.load(std::memory_order_acquire)) {
if (next == nullptr) {
// last->next๊ฐ ๋น์ด์์ผ๋ฉด ์ ๋
ธ๋๋ฅผ ์ฐ๊ฒฐ ์๋
if (std::atomic_compare_exchange_weak_explicit(
&last->next,
&next,
newNode,
std::memory_order_release,
std::memory_order_relaxed)) {
// ์ฑ๊ณต์ ์ผ๋ก ์ฐ๊ฒฐํ์ผ๋ฉด tail์ ์
๋ฐ์ดํธ ์๋
std::atomic_compare_exchange_weak_explicit(
&tail,
&last,
newNode,
std::memory_order_release,
std::memory_order_relaxed);
return;
}
} else {
// ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์ด๋ฏธ ์ฐ๊ฒฐํ์ผ๋ฏ๋ก tail์ ์์ผ๋ก ๋น๊ธด๋ค
std::atomic_compare_exchange_weak_explicit(
&tail,
&last,
next,
std::memory_order_release,
std::memory_order_relaxed);
}
}
// CAS ์คํจ ์ ๋ฃจํ ๋ฐ๋ณต
}
}
// try_pop: ์ฑ๊ณตํ๋ฉด optional<T> ๋ฐํ, ์คํจํ๋ฉด nullopt
std::optional<T> try_pop() {
while (true) {
Node* first = head.load(std::memory_order_acquire);
Node* last = tail.load(std::memory_order_acquire);
Node* next = first->next.load(std::memory_order_acquire);
if (first == head.load(std::memory_order_acquire)) {
if (first == last) {
if (next == nullptr) {
// ํ๊ฐ ๋น์ด์์
return std::nullopt;
}
// tail์ด ๋ค์ณ์ ธ ์์ผ๋ฏ๋ก ๋น๊ฒจ์ค๋ค
std::atomic_compare_exchange_weak_explicit(
&tail,
&last,
next,
std::memory_order_release,
std::memory_order_relaxed);
} else {
// ์ค์ ๋ก pop ํ ์ ์๋ ๋
ธ๋(next)๊ฐ ์กด์ฌ
std::shared_ptr<T> result = next->data;
// head๋ฅผ next๋ก ๊ต์ฒด (CAS)
if (std::atomic_compare_exchange_weak_explicit(
&head,
&first,
next,
std::memory_order_release,
std::memory_order_relaxed)) {
// ์์ ํ๊ฒ ์ฒซ ๋
ธ๋ ์ญ์
// <-- ์ฃผ์: ์ด ๋จ๊ณ์์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฌ์ฉ(ABA) ๋ฌธ์ ๊ฐ ์์ ์ ์์.
delete first;
if (result) return *result;
else return std::nullopt;
}
}
}
// CAS ์คํจ ์ ๋ฐ๋ณต
}
}
bool empty() const {
Node* h = head.load(std::memory_order_acquire);
Node* n = h->next.load(std::memory_order_acquire);
return n == nullptr;
}
};
- ๋๋ฏธ(dummy) ๋ ธ๋: MS ํ๋ ํญ์ ํ๋์ ๋๋ฏธ ๋ ธ๋๋ฅผ ์ ์งํ์ฌ head์ tail ์ ๋ฐ์ดํธ๋ฅผ ๋จ์ํํฉ๋๋ค. ์ค์ ์ฒซ ์ ํจ ๋ฐ์ดํฐ๋ head->next์์ ์์ํฉ๋๋ค.
- ์์์ฑ(atomic): head, tail, ๊ทธ๋ฆฌ๊ณ ๊ฐ ๋ ธ๋์ next๋ std::atomic<Node*>๋ก ์ ์ธ๋์ด CAS๋ก ๊ฐฑ์ ํฉ๋๋ค.
- enqueue ํ๋ฆ:
- tail๊ณผ tail->next๋ฅผ ์ฝ๊ณ , tail->next๊ฐ nullptr์ด๋ฉด ์ฌ๊ธฐ์ ์ ๋ ธ๋๋ฅผ CAS๋ก ์ฐ๊ฒฐ.
- ์ฐ๊ฒฐ ์ฑ๊ณตํ๋ฉด tail์ ์ ๋ ธ๋๋ก CAS๋ก ์ด๋(์คํจํด๋ ๋ฌดํด).
- dequeue ํ๋ฆ:
- head, tail, head->next๋ฅผ ์ฝ๋๋ค.
- head == tail ์ด๊ณ head->next == nullptr์ด๋ฉด ํ๋ ๋น์ด์์.
- head != tail์ด๋ฉด head๋ฅผ head->next๋ก CAS๋ก ์ฎ๊ธฐ๊ณ , ์ฑ๊ณต ์ ์ด์ head๋ ์ญ์ .
์ถ๊ฐ ์ฒดํฌ ํฌ์ธํธ
- ABA ๋ฌธ์ : ํฌ์ธํฐ๊ฐ A -> B -> A์ฒ๋ผ ์ฌ์ฌ์ฉ๋๋ฉด CAS๊ฐ ์ฑ๊ณตํด๋ ์๋ชป๋ ์ํ๊ฐ ๋ ์ ์์. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ํฌ์ธํฐ์ ํ๊ทธ(์นด์ดํฐ)๋ฅผ ๋ถ์ด๊ฑฐ๋ Hazard Pointers / epoch-based reclamation ๋ฑ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
- ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฌ์ฉ ๋ฐ ์์ ํ ์ญ์ : ์ ๊ตฌํ์ ๊ฐ๋จํ ์ํด delete first;๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ํ์ง๋ง ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์ฌ์ ํ ํด๋น ๋
ธ๋ ์ฃผ์๋ฅผ ์ฐธ์กฐํ๊ณ ์์ ์ ์์ผ๋ฏ๋ก ์์ ํ์ง ์์ ์ ์์ต๋๋ค. ์์ ํ ๋ฐฉ๋ฒ:
- Hazard pointers (๊ถ์ฅ) — ๋ ธ๋๋ฅผ ์ ๊ทผ ์ค์ธ ์ค๋ ๋๋ฅผ ๋ช ์์ ์ผ๋ก ํ์ํด์ ์์ ํ ๋๋ง ์ญ์ .
- Epoch-based reclamation (๋ ๋น ๋ฆ, ๋ณต์ก์ฑ ์์).
- ํน์ ์ด๋ฏธ ๊ฒ์ฆ๋ ๊ตฌํ ์ฌ์ฉ: boost::lockfree::queue, Folly, concurrency kit ๋ฑ.
- ๋ฉ๋ชจ๋ฆฌ ์ค๋ฒํค๋ vs ์ฑ๋ฅ: shared_ptr๋ฅผ ๋ ธ๋ ๋ฐ์ดํฐ์ ์ฌ์ฉํ๋ฉด ์์ ํ๋ ํ ๋น/์ฐธ์กฐ ์นด์ดํธ ๋น์ฉ์ด ์๊น๋๋ค. ์ด๊ณ ์ฑ๋ฅ(low-latency) ํ๊ฒฝ์์๋ hazard/epoch ๋ฐฉ์์ผ๋ก raw pointer์ ๋น ๋ฅธ reclamation ์กฐํฉ์ด ์ ํธ๋ฉ๋๋ค.
์กฐ๊ธ ๋ ์ฌ์ด ๋ฒ์ ์ธ CAS stack ์์ ๋ ํจ๊ป ๋ณด๊ฒ ์ต๋๋ค.
#include <atomic>
#include <iostream>
#include <thread>
template <typename T>
struct Node {
T value;
Node* next;
Node(T v) : value(v), next(nullptr) {}
};
template <typename T>
class LockFreeStack {
private:
std::atomic<Node<T>*> head;
public:
LockFreeStack() : head(nullptr) {}
void push(T value) {
Node<T>* newNode = new Node<T>(value);
newNode->next = head.load(std::memory_order_relaxed);
// head๋ฅผ newNode๋ก ๊ต์ฒด ์๋ (CAS ๋ฃจํ)
while (!head.compare_exchange_weak(
newNode->next, newNode,
std::memory_order_release,
std::memory_order_relaxed)) {
// ์คํจํ๋ฉด newNode->next๋ฅผ ์ต์ head๋ก ๊ฐฑ์ ํ๊ณ ์ฌ์๋
}
}
bool pop(T& result) {
Node<T>* oldHead = head.load(std::memory_order_relaxed);
// head๋ฅผ oldHead->next๋ก ๊ต์ฒด ์๋ (CAS ๋ฃจํ)
while (oldHead != nullptr &&
!head.compare_exchange_weak(
oldHead, oldHead->next,
std::memory_order_acquire,
std::memory_order_relaxed)) {
// ์คํจ ์ oldHead๊ฐ ์ต์ ๊ฐ์ผ๋ก ์๋ ๊ฐฑ์ ๋จ
}
if (oldHead == nullptr) return false;
result = oldHead->value;
delete oldHead;
return true;
}
};
int main() {
LockFreeStack<int> stack;
// ์ฌ๋ฌ ์ค๋ ๋์์ ๋์์ push/pop
std::thread t1([&]() {
for (int i = 0; i < 5; i++) stack.push(i);
});
std::thread t2([&]() {
for (int i = 5; i < 10; i++) stack.push(i);
});
t1.join();
t2.join();
int value;
while (stack.pop(value)) {
std::cout << value << " ";
}
std::cout << std::endl;
return 0;
}
CAS ๊ธฐ๋ฐ์ Lock-Free Stack ๊ธฐ๋ณธ ํํ์ ๋๋ค. ๋ฝ ์์ด ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ `push`์ `pop`์ ์์ ํ๊ฒ ์ํํ ์ ์์ต๋๋ค. ๋ ์์ ๋ชจ๋ ABA ํด๊ฒฐ ์ ๋ต๊ณผ ๋ฉ๋ชจ๋ฆฌ ํ์ ์ ๋ต์ด ํ์์ ๋๋ค. ๋ณด์ฌ๋๋ฆฐ ์์ ์์๋ ๊ฐ๋จํ ์์ ์์๋ ๋ฌธ์ ๊ฐ ์์ง๋ง ๋ณต์กํ ์ค๋ฌด์์๋ ์ถ๊ฐ์ ์ธ ์์ธ ์ฅ์น๊ฐ ๋ฐ๋์ ํ์ํ ๊ฒ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ C++์์์ compare_exchange_weak, memory_order๋ ๋ฐ๋ก ํฌ์คํ ์ ์งํํ ๊ณํ์ ๋๋ค.

๋ง์น๋ฉฐ
CAS๋ฅผ ํตํ ๊ฒฝ์์ํ ํด๊ฒฐ๋ฐฉ์์ ๊ธฐ์กด Lock๊ณผ๋ ์กฐ๊ธ ๋ค๋ฆ ๋๋ค. while๋ฌธ์ ๋๊ธฐ์์ด ๋ฌดํ๋ฃจํ์ฒ๋ผ ๋ฐ๋ณตํ๋ฉด์ waiting์ ํ๋ ๋ชจ์ต์ ๋๋ค. ๋๊ตฐ๊ฐ๋ backoff ์ ๋ต์ผ๋ก 1~10ns sleep์ ์ ์ฉํ๋ค๊ณ ํ์ง๋ง, ์ด๋ ๋ฌธ๋งฅ ๊ตํ์ด ๋ฐ์ํ ์ฌ์ง๊ฐ ์์ต๋๋ค. ๋๊ธฐ ์๋ polling์ด ์ด์ฉ๋ฉด ์ฑ๋ฅ์๋ ๊ฐ์ฅ ์ข์ ์ ๋ต์ด ์๋๊น ์ถ์ต๋๋ค. Lock Free์ ๊ธฐ์ด๊ฐ๋ ์ธ CAS ์๊ณ ๋ฆฌ์ฆ์, CPU๊ฐ ์งํํ๋ ค๋ ํ๋ฆ์ OS ๊ฐ์ญ(Context Switching) ์์ด ์บ์ ์ง์ญ์ฑ์ ๋์ผ ์ ์๋ ์ค์ ๊ฐ๋ ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๋๊ธ