[Rust] AtomicBool과 Ordering: 개념과 활용과 Crossbeam까지

[Rust] AtomicBool과 Ordering: 개념과 활용과 Crossbeam까지

Rust/Libraries
민호이 민호이 2025. 1. 13. 01:46
목차
  1. Rust의 AtomicBool과 관련된 개념 및 라이브러리 총정리
  2. 1. AtomicBool이란?
  3. 2. AtomicBool의 주요 메서드
  4. 3. 메모리 순서 (Ordering)
  5. 4. AtomicBool의 활용 사례
  6. 4.1 플래그 기반의 상태 확인
  7. 4.2 스핀 락(Spin Lock) 구현
  8. 5. 관련 라이브러리와 개념
  9. 5.1 Crossbeam
  10. 5.2 std::sync::Arc와 결합
  11. 5.3 async-std와 Tokio에서의 사용
  12. 6. AtomicBool의 장단점
  13. 결론

Rust의 AtomicBool과 관련된 개념 및 라이브러리 총정리

Rust의 AtomicBool은 다중 스레드 환경에서 **불리언 값(boolean)**을 안전하게 공유하고 수정할 수 있도록 설계된 원자적(atomic) 데이터 타입입니다. 이 글에서는 AtomicBool의 개념, 사용 방법, 그리고 관련 라이브러리와 유용한 패턴을 종합적으로 정리합니다.


1. AtomicBool이란?

AtomicBool은 단일 비트 값(true 또는 false)을 다중 스레드에서 안전하게 읽고 쓸 수 있는 원자적 타입입니다. std::sync::atomic 모듈에 포함되어 있으며, 내부적으로 CPU의 원자적 연산을 활용하여 동기화 문제를 해결합니다.

주요 특징

  • 원자적 연산: 동시성 제약 없이 값의 읽기, 쓰기, 변경이 가능합니다.
  • CAS(compare-and-swap) 연산 지원: 값의 상태를 비교하고 조건에 따라 원자적으로 변경.
  • 메모리 순서 지정: 연산의 메모리 순서를 제어하기 위해 Ordering을 사용.

AtomicBool 사용 예제

use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
fn main() {
let is_ready = AtomicBool::new(false);
let handle = thread::spawn({
let is_ready = &is_ready;
move || {
is_ready.store(true, Ordering::SeqCst);
}
});
while !is_ready.load(Ordering::SeqCst) {
// Spin-wait
}
println!("Ready!");
handle.join().unwrap();
}

2. AtomicBool의 주요 메서드

메서드 설명
new(value: bool) 새로운 AtomicBool을 생성. 초기값을 설정.
load(order: Ordering) AtomicBool의 현재 값을 읽음.
store(value: bool, order: Ordering) AtomicBool에 새 값을 저장.
compare_and_swap(current: bool, new: bool, order: Ordering) current 값과 비교 후, 동일하면 new 값으로 변경 (Rust 1.50부터 compare_exchange로 대체).
compare_exchange(current: bool, new: bool, success: Ordering, failure: Ordering) 성공과 실패에 대해 메모리 순서를 지정하며 CAS 수행.
fetch_and(value: bool, order: Ordering) 현재 값과 주어진 값의 AND 연산 결과를 저장 후 이전 값을 반환.
fetch_or(value: bool, order: Ordering) 현재 값과 주어진 값의 OR 연산 결과를 저장 후 이전 값을 반환.

3. 메모리 순서 (Ordering)

AtomicBool은 연산의 메모리 순서를 제어하기 위해 Ordering 열거형을 사용합니다. 이는 동기화의 강도와 성능 간의 균형을 결정합니다.

Ordering 설명
Relaxed 메모리 순서를 신경 쓰지 않음. 성능은 높지만 동기화 보장이 약함.
Acquire 읽기 연산이 이전의 모든 쓰기 연산을 관찰할 수 있도록 보장.
Release 쓰기 연산이 이후의 모든 읽기 연산보다 먼저 실행되도록 보장.
AcqRel 읽기와 쓰기 모두 동기화. Acquire와 Release의 조합.
SeqCst 모든 스레드 간의 연산 순서를 강력히 보장 (가장 느리지만 안전).

4. AtomicBool의 활용 사례

4.1 플래그 기반의 상태 확인

다중 스레드에서 작업 완료 여부를 플래그로 관리할 때 유용합니다.

use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
fn main() {
let is_done = AtomicBool::new(false);
let handle = thread::spawn({
let is_done = &is_done;
move || {
// 작업 수행
println!("작업 완료!");
is_done.store(true, Ordering::SeqCst);
}
});
while !is_done.load(Ordering::SeqCst) {
// 작업 완료를 대기
}
println!("모든 작업이 완료되었습니다!");
handle.join().unwrap();
}

4.2 스핀 락(Spin Lock) 구현

AtomicBool을 사용해 간단한 스핀 락을 구현할 수 있습니다.

use std::sync::atomic::{AtomicBool, Ordering};
pub struct SpinLock {
flag: AtomicBool,
}
impl SpinLock {
pub fn new() -> Self {
SpinLock {
flag: AtomicBool::new(false),
}
}
pub fn lock(&self) {
while self.flag.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() {}
}
pub fn unlock(&self) {
self.flag.store(false, Ordering::Release);
}
}

5. 관련 라이브러리와 개념

5.1 Crossbeam

Crossbeam은 고급 동시성 프로그래밍을 지원하는 라이브러리로, AtomicBool과 함께 안전하고 효율적인 작업을 구현할 수 있습니다. 예를 들어, AtomicCell은 원자적으로 값을 관리할 수 있는 일반적인 구조를 제공합니다.

[dependencies]
crossbeam = "0.8"
use crossbeam::atomic::AtomicCell;
fn main() {
let atomic_value = AtomicCell::new(42);
atomic_value.store(100);
println!("Atomic Value: {}", atomic_value.load());
}

5.2 std::sync::Arc와 결합

AtomicBool은 Arc와 결합하여 다중 스레드 간 안전한 데이터 공유에 활용됩니다.

use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
use std::thread;
fn main() {
let flag = Arc::new(AtomicBool::new(false));
let handles: Vec<_> = (0..5)
.map(|_| {
let flag = Arc::clone(&flag);
thread::spawn(move || {
while !flag.load(Ordering::Acquire) {
// 대기 중
}
println!("Flag set to true!");
})
})
.collect();
// 플래그 설정
flag.store(true, Ordering::Release);
for handle in handles {
handle.join().unwrap();
}
}

5.3 async-std와 Tokio에서의 사용

비동기 작업에서도 AtomicBool을 활용해 작업 흐름을 제어할 수 있습니다.

use std::sync::atomic::{AtomicBool, Ordering};
use tokio::task;
#[tokio::main]
async fn main() {
let is_ready = AtomicBool::new(false);
let task = task::spawn(async {
is_ready.store(true, Ordering::SeqCst);
});
while !is_ready.load(Ordering::SeqCst) {
// 비동기 대기
}
println!("Ready!");
task.await.unwrap();
}

6. AtomicBool의 장단점

장점 단점
메모리 락 없이 동기화 가능 메모리 순서와 동기화를 잘못 설정하면 버그 발생 가능
성능이 뛰어남 (락 오버헤드 없음) 복잡한 상태 관리에는 부적합하며 추가 도구가 필요
CAS와 메모리 순서 제어 지원 코드 복잡성 증가 (Ordering의 올바른 사용 필요)

결론

Rust의 AtomicBool은 다중 스레드 환경에서 간단한 상태 제어와 동기화를 제공하는 강력한 도구입니다. 스핀 락, 플래그 관리, 상태 변경 감지 등 다양한 동시성 작업에서 활용될 수 있습니다. Ordering 개념을 잘 이해하고, 필요에 따라 Arc, Crossbeam 같은 도구와 결합하면 더욱 복잡한 동시성 문제를 안전하고 효율적으로 해결할 수 있습니다.

저작자표시 비영리 변경금지 (새창열림)
  1. Rust의 AtomicBool과 관련된 개념 및 라이브러리 총정리
  2. 1. AtomicBool이란?
  3. 2. AtomicBool의 주요 메서드
  4. 3. 메모리 순서 (Ordering)
  5. 4. AtomicBool의 활용 사례
  6. 4.1 플래그 기반의 상태 확인
  7. 4.2 스핀 락(Spin Lock) 구현
  8. 5. 관련 라이브러리와 개념
  9. 5.1 Crossbeam
  10. 5.2 std::sync::Arc와 결합
  11. 5.3 async-std와 Tokio에서의 사용
  12. 6. AtomicBool의 장단점
  13. 결론
'Rust/Libraries' 카테고리의 다른 글
  • [Rust] HashMap, HashSet 전격 비교, 차이점
  • [Rust] Arc, Mutex: 개념과 예제, 사용법
  • [Rust] spawn와 scope의 차이 (std::thread): 개념과 예제
  • [Rust] Box 활용 완벽 정리: 예제, 메소드
민호이
민호이
민호이
ChungCODE
민호이
전체
오늘
어제
  • Categories (128)
    • 스포츠 (6)
    • 인공지능 (5)
    • 주식 (6)
      • 경제 주식 전망 (5)
      • ETF (9)
    • CSAPP (4)
      • Lab Session (4)
      • Concepts (0)
    • C (19)
    • Java (24)
    • Rust (44)
      • Concepts (27)
      • Libraries (17)
    • PS (2)
    • 국내 소식 (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 최대공약수
  • 최소공배수
  • 코드업
  • C
  • c++
  • 유클리드 호제법
  • 알고리즘
  • 수학

최근 댓글

최근 글

반응형
hELLO · Designed By 정상우.v4.2.1
민호이
[Rust] AtomicBool과 Ordering: 개념과 활용과 Crossbeam까지
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.