concurrency

5 posts
Rust 기초: LazyLock과 OnceLock으로 전역 값 지연 초기화하기

Rust 기초: LazyLock과 OnceLock으로 전역 값 지연 초기화하기

전역에 룩업 테이블(lookup table) 하나 두고 싶을 뿐인데, Rust에서는 이게 생각보다 까다롭습니다. 해시맵을 static으로 선언하려고 하면 컴파일러가 바로 막아서거든요. static에 넣는 값은 컴파일 시점에 계산이 끝나 있어야 하는데, HashMap::from은 실행 중에 힙을 할당하니 안 된다는 뜻입니다. 예전에는 lazy_static! 매크로나 once_cell 크레이트(crate)를 받아 와서 풀던 문제인데요. 이제는 외부 의존성 없이 해결됩니다. 에러 메시지 마지막 줄에서 컴파일러가 이미 답을 알려주고 있네요

Rust 기초: 원자적 타입과 메모리 오더링

Rust 기초: 원자적 타입과 메모리 오더링

여러 스레드에서 카운터 하나를 안전하게 올리고 싶을 때 가장 먼저 떠오르는 게 Mutex<i32>인데요. 그런데 막상 짜놓고 보면 "고작 정수 하나 더하자고 잠금을 잡았다 풀었다 한다고?" 싶어집니다. 실제로 이 패턴은 Sync 트레이트 글에서도 잠깐 언급했던 원자적 타입을 쓰면 훨씬 가볍게 해결할 수 있어요. Mutex도 Arc도 안 보이는데 5,000이 정확히 출력됩니다. 그런데 이 코드를 처음 보면 두 가지가 좀 거슬리는데요. &counter로 변경이 되는 게 어떻게 가능한지, 그리고 저 Ordering::Relaxed는 도대

Rust 기초: Sync 트레이트로 스레드 간 안전한 참조 공유하기

Rust 기초: Sync 트레이트로 스레드 간 안전한 참조 공유하기

Send 트레이트를 공부하다 보면 자연스럽게 따라오는 질문이 있는데요. "값을 스레드로 옮기지 않고, 여러 스레드에서 동시에 참조만 하고 싶으면 어떻게 하지?" 예를 들어 Arc로 RefCell을 감싸서 여러 스레드에서 접근하려고 하면 이런 컴파일 에러가 납니다. "스레드 간에 안전하게 공유할 수 없다"는 이 에러의 핵심이 바로 Sync 트레이트입니다. Send가 소유권 이동의 안전성을 보장한다면, Sync는 참조 공유의 안전성을 보장하는 건데요. 이 글에서 Sync가 어떤 역할을 하고 어떤 타입이 Sync이고 어떤 타입은 아닌지,

Rust 기초: Send 트레이트로 스레드 안전성 보장하기

Rust 기초: Send 트레이트로 스레드 안전성 보장하기

Rust로 멀티스레드 프로그래밍을 하다 보면 이런 컴파일 에러를 만나게 되는 경우가 있는데요. "스레드 간에 안전하게 보낼 수 없다"는 말은 대체 무슨 뜻일까요? 그리고 Send 트레이트는 뭘까요? 🤔 사실 이 에러 메시지 안에 Rust가 동시성 프로그래밍에서 데이터 경합(data race)을 원천 차단하는 메커니즘이 담겨 있습니다. Send 트레이트가 어떻게 동작하고, 어떤 상황에서 우리를 보호해 주는지 살펴볼게요. Send 트레이트란? Send는 Rust 표준 라이브러리의 std::marker 모듈에 정의된 마커 트레이트(ma

Rust 기초: Mutex와 RwLock으로 스레드 간 데이터 수정하기

Rust 기초: Mutex와 RwLock으로 스레드 간 데이터 수정하기

Arc로 데이터를 여러 스레드에 나눠 주는 것까지는 잘됩니다. 그런데 그 데이터를 고치려고 하면 막히죠. Arc가 불변 참조만 주기 때문인데요. 단일 스레드에서라면 RefCell로 풀던 문제라, 똑같이 감싸 보면 어떨까 싶어집니다. RefCell이 빌림을 세는 카운터에는 아무런 동기화가 없어서, 여러 스레드가 동시에 건드리면 숫자가 꼬입니다. 그래서 Sync를 구현하지 않고, 컴파일러가 미리 막아 주는 거예요. 여기서 필요한 게 Mutex입니다. 이름은 상호 배제(mutual exclusion)에서 왔는데, 말 그대로 한 번에 하나

Discord