खोज…


परिचय

बताएं कि कुछ चीजों को Rust में 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) से कम होगा।

इस उदाहरण में, एक डेटा रेस ने तार्किक रूप से गलत लेकिन फिर भी सार्थक मूल्य का उत्पादन किया है। इसका कारण यह है कि केवल एक ही शब्द दौड़ में शामिल था और इस प्रकार एक अद्यतन आंशिक रूप से इसे बदल नहीं सकता था। लेकिन सामान्य रूप से डेटा दौड़ भ्रष्ट मान उत्पन्न कर सकती है जो एक प्रकार (प्रकार असुरक्षित) के लिए अमान्य हैं जब ऑब्जेक्ट कई शब्दों के लिए फैलाया जा रहा है, और / या ऐसे मान उत्पन्न करता है जो पॉइंटर्स में शामिल होने पर अमान्य मेमोरी स्थानों (मेमोरी असुरक्षित) को इंगित करते हैं।

हालांकि, परमाणु प्राइमेटिक्स का सावधानीपूर्वक उपयोग बहुत कुशल डेटा संरचनाओं के निर्माण को सक्षम कर सकता है, जिन्हें आंतरिक रूप से इनमें से कुछ "असुरक्षित" संचालन करने की आवश्यकता हो सकती है, जो उन कार्यों को करने के लिए हैं, जो रुस्त के प्रकार प्रणाली द्वारा सांख्यिकीय रूप से सत्यापित नहीं हैं, लेकिन समग्र रूप से (एक सुरक्षित निर्माण के लिए) अमूर्त)।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow