수색…


소개

특정 사물이 녹에서 unsafe 것으로 표시되는 이유와 특정 (희귀 한) 상황에서이 탈출구를 사용해야하는 이유를 설명하십시오.

데이터 경주

데이터 경쟁은 한 파티에 의해 메모리 조각이 업데이트되고 다른 파티클이 동시에 동기화를하지 않고 동시에 업데이트하거나 읽으려고 할 때 발생합니다. 공유 카운터를 사용하여 데이터 경쟁의 고전적인 예를 살펴 보겠습니다.

use std::cell::UnsafeCell;
use std::sync::Arc;
use std::thread;

// `UnsafeCell` is a zero-cost wrapper which informs the compiler that "what it
// contains might be shared mutably." This is used only for static analysis, and
// gets optimized away in release builds.
struct RacyUsize(UnsafeCell<usize>);

// Since UnsafeCell is not thread-safe, the compiler will not auto-impl Sync for
// any type containig it. And manually impl-ing Sync is "unsafe".
unsafe impl Sync for RacyUsize {}

impl RacyUsize {
    fn new(v: usize) -> RacyUsize {
        RacyUsize(UnsafeCell::new(v))
    }

    fn get(&self) -> usize {
        // UnsafeCell::get() returns a raw pointer to the value it contains
        // Dereferencing a raw pointer is also "unsafe"
        unsafe { *self.0.get() }
    }

    fn set(&self, v: usize) { // note: `&self` and not `&mut self`
        unsafe { *self.0.get() = v }
    }
}

fn main() {
    let racy_num = Arc::new(RacyUsize::new(0));

    let mut handlers = vec![];
    for _ in 0..10 {
        let racy_num = racy_num.clone();
        handlers.push(thread::spawn(move || {
            for i in 0..1000 {
                if i % 200 == 0 {
                    // give up the time slice to scheduler
                    thread::yield_now();
                    // this is needed to interleave the threads so as to observe
                    // data race, otherwise the threads will most likely be
                    // scheduled one after another.
                }

                // increment by one
                racy_num.set(racy_num.get() + 1);
            }
        }));
    }

    for th in handlers {
        th.join().unwrap();
    }

    println!("{}", racy_num.get());
}

멀티 코어 프로세서에서 실행될 때 출력은 거의 항상 10000 (10 스레드 × 1000) 미만입니다.

이 예에서 데이터 경쟁은 논리적으로 잘못되었지만 여전히 의미있는 가치를 창출했습니다. 이는 한 단어 만 경주에 참여했기 때문에 업데이트로 부분적으로 변경하지 못했기 때문입니다. 그러나 일반적으로 데이터 레이스는 여러 단어에 걸쳐 경주하는 개체가있을 때 형식이 안전하지 않은 손상된 값을 생성하거나 포인터가 관련된 잘못된 메모리 위치 (메모리가 안전하지 않음)를 가리키는 값을 생성 할 수 있습니다.

그러나 원자 기본 요소를주의 깊게 사용하면 Rust의 유형 시스템에서 정적으로 검증 할 수없는 작업을 수행하기 위해 내부적으로 이러한 "안전하지 않은"작업 중 일부를 내부적으로 수행해야하는 매우 효율적인 데이터 구조를 구축 할 수 있지만 전반적인 작업 (즉, 추출).



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow