C.W.K.
Stream
Lesson 02 of 05 · published

스레드를 넘는 move 클로저

~10 min · concurrency, move, ownership

Level 0Rust 호기심러
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

spawn 된 스레드는 만든 스코프보다 오래 살 수 있어. 그래서 클로저가 그 스코프의 데이터를 쓸 때 Rust 는 질문에 부딪혀: 스레드가 읽을 때 데이터가 아직 살아있을까? move 키워드가 답해.

스레드는 왜 move 클로저가 필요해

스레드 클로저가 지역 변수를 빌렸는데 spawn 한 함수가 스레드 끝나기 전에 반환하면, borrow 가 dangle 해 — 전형적 use-after-free. Rust 가 그걸 컴파일 거부해. 수정은 move: 클로저가 캡처한 걸 소유 해서, 데이터가 원래 스코프와 무관하게 스레드만큼 오래 살아.

소유권이 스레드 경계를 넘어

move 로, 캡처된 값이 스레드로 이전돼. spawn 한 스레드는 더는 못 써 — 이제 새 스레드 거야. Ownership 트랙의 그 move 시맨틱을 스레드 경계에 적용한 거고, 바로 그게 이전을 안전하게 해: 한 스레드만 데이터를 소유.

move 가 스레드를 데이터의 owner 로 만들어, 아무것도 dangle 못 해. 소유권을 클로저로 이전해서, Rust 가 데이터가 스레드보다 오래 살고 spawn 한 쪽이 더는 안 건드린다고 보장해. borrow checker 의 dangling 참조 규칙을 스레드 간에 강제한 거야.

move 말고 공유는?

가끔 데이터를 한 스레드한테 주고 싶지 않아 — 여러 스레드가 공유 하길 원해. 한 값을 여러 클로저로 move 못 해. 거기서 Arc (Smart Pointers 트랙) 가 돌아와: 스레드마다 Arc 를 clone 하면, 각 스레드가 같은 데이터로의 공유 핸들을 소유해. 다음 두 레슨이 바로 그 위에 지어.

Code

move 가 소유권을 스레드로 이전한다·rust
use std::thread;

fn main() {
    let data = vec![1, 2, 3];

    // `move` 가 `data` 소유권을 스레드로 이전
    let handle = thread::spawn(move || {
        println!("thread owns {data:?}");
        data.iter().sum::<i32>()
    });
    // data 는 여기서 더는 못 써 — 이제 스레드가 소유

    let total = handle.join().unwrap();
    println!("sum: {total}");
}

External links

Exercise

String 을 만들고, 그걸 소유해서 출력하는 move 클로저로 스레드를 spawn 해. 그 뒤 main 에서 String 을 못 쓰는 걸 확인해. 그다음 move 를 빼고 borrow 에러를 읽어 — 컴파일러가 정확히 뭘 걱정하는 거야?
Hint
move 없으면 클로저가 String 을 빌리는데, 스레드가 main 의 String 스코프보다 오래 살 수 있어 — dangling borrow. move 가 소유권을 이전해 스레드가 필요한 만큼 데이터를 살려둬.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.