서버에서 공유 자원을 여러 스레드가 동시에 수정하도록 구현하고 있는데, 특정 조건에서 서버가 응답하지 않고 멈춰버립니다.
코드:
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let data = Arc::new(Mutex::new(0));
let data_clone = Arc::clone(&data);
let handle = thread::spawn(move || {
let lock = data_clone.lock().unwrap();
println!("Thread 1 lock acquired");
let _lock2 = data_clone.lock().unwrap();
});
let lock = data.lock().unwrap();
println!("Main lock acquired");
handle.join().unwrap();
}
오류: Main lock acquired 출력 이후 프로그램이 종료되지 않고 무한 대기 상태에 빠짐.
시도: Mutex 대신 RwLock으로 바꿔봤지만 여전히 같은 지점에서 멈췄고, lock 범위를 줄여보려 했으나 구조상 어려움이 있었습니다.
질문: Rust의 Mutex는 동일한 스레드에서 중복으로 lock을 요청했을 때 왜 자동으로 처리되지 않고 데드락이 발생하는 건가요?
댓글12
-
빗방울
2026.10.30 05:32
-
빗방울
2026.10.30 05:56
맞음ㅋㅋ 굳이 재귀 락 쓰고 싶으면 parking_lot 크레이트 써보는 것도 방법일듯요.
-
빗방울
2026.10.30 05:41
메인 스레드에서 락 잡고 join 기다리는 게 제일 큰 문제인듯요.
순서상 메인이 락을 안 놔주니까 스레드가 영원히 대기타는 구조네요.
메인 락 범위를 중괄호로 묶어서 먼저 해제해보세요.
-
빗방울
2026.10.30 05:58
이거 전형적인 입문자 실수네요ㅋㅋ
그냥 lock 잡은 상태에서 무한 루프나 대기 타는 구간 있는지 한번 더 훑어보세요.
-
빗방울
2026.10.30 12:32
ㄹㅇㅋㅋ 특히 러스트는 가드 변수 수명 때문에 락이 생각보다 길게 유지돼서 더 헷갈리는 것 같음요.
-
빗방울
2026.10.30 06:14
코드 보니까 스레드 내부에서도 셀프 데드락 걸릴 구조네요.
한 번 잡은 락 안 놓고 또 lock() 호출하면 바로 멈춤ㅋㅋ
그냥 락 잡는 로직을 함수로 따로 빼서 스코프 관리하는 게 제일 깔끔할듯요.
-
빗방울
2026.10.30 08:02
그냥 `drop(lock)` 명시적으로 써보세요.
그게 제일 확실하고 편함ㅋㅋ
스코프 꼬일 때는 그게 약임.
-
빗방울
2026.10.30 09:08
이거 그냥 `let _lock = ...` 이렇게 쓰면 바로 드롭되는데
변수 이름 지정해서 잡고 계셔서 계속 유지되는 거 아님?ㅋㅋ
그냥 값만 필요하신 거면 바로 쓰고 버리세요.
-
빗방울
2026.10.30 12:36
근데 이거 `_lock`으로 이름 지어도 어차피 가드가 변수에 할당된 거라 스코프 끝날 때까지 안 풀릴걸요ㅋㅋ
그냥 `drop` 때리거나 블록으로 감싸는 게 제일 확실할 듯요.
-
빗방울
2026.10.30 09:46
이거 그냥 MutexGuard가 스코프 끝날 때까지 안 풀려서 그런 거 같은데 락 잡는 부분만 블록 { }으로 감싸보세요ㅋㅋ 그게 제일 직관적임.
-
빗방울
2026.10.30 10:41
와 진짜 데드락 늪에 빠지면 답도 없죠ㅋㅋ
이거 그냥 `Mutex` 대신 `Atomic` 계열로 바꿀 수 있는 구조면 그게 정신건강에 훨씬 이로울 것 같은데요.
데이터 타입이 단순 정수면 굳이 락 안 잡고 `AtomicI32` 같은 거 써보세요.
-
빗방울
2026.10.30 12:03
그냥 `std::sync::Mutex` 쓰면서 이런거 겪으면 진짜 킹받죠ㅋㅋ 내 생각엔 락 잡는 순서 자체를 아예 설계 단계부터 다시 짜보는 게 나중에 고생 안 하는 길인 듯요.
모든 이야기1464
가벼운 안부부터 깊은 생각까지, 함께 나눠요.
러스트 Mutex는 재귀 락을 지원 안 해서 그래요.
내 생각엔 그냥 lock 변수 빨리 드롭시키거나
try_lock 써보는 게 빠를듯ㅋㅋ