"command는 여럿, 메모리는 하나, 어쩌면 동시에. 락이 걔들이 서로를 밟지 않게 막아주는 거야."
왜 그냥 못 바꾸나
managed state는 공유 참조를 쥐여주는데, Rust는 공유 참조로 값을 바꾸는 걸 막아. command 둘이 동시에 돌면서 데이터를 망가뜨릴 수 있으니까. 대신 안전하게 바꾸는 길이 interior mutability야. 바뀔 데이터를 Mutex<T>로 감싸는 거지. 바꾸려면 Mutex를 lock()하고, 그 락 가드가 살아 있는 동안엔 나 혼자만 만져. 락을 잡으려던 다른 command는 차례를 기다리고. 쓰다 만 값도, 레이스도 없어 — 강제로.
락은 짧게 잡고 빨리 놔
락은 가능한 한 짧게 쥐어. 잠그고, 바꾸고, 가드를 놔주고(보통 스코프가 끝나면 알아서 놔) 끝. 오래 쥔 락은 앱 전체를 그 Mutex 하나 앞에 줄 세워. 쓰기보다 읽기가 훨씬 많은 state엔 RwLock이 나아. 읽는 쪽은 여럿이 동시에 들여보내고 쓸 때만 막아주거든 — 캐시나 가끔 갱신되는 설정에 딱이야.
async 함정 (또 나왔어)
bridge 트랙의 Send 규칙 기억나? std::sync::Mutex 가드를 .await 너머까지 쥐고 있으면 안 돼. async command에선 컴파일이 안 되고, 된다 쳐도 deadlock 위험이야. await 전에 가드를 놔주거나(잠그고, 필요한 걸 복사하고, 풀고, 그다음 await) tokio::sync::Mutex처럼 async를 아는 Mutex를 써. command 대부분은 잠그고-복사하고-푸는 쪽이 제일 단순하고 빨라.