Rust में समवर्तीता और मल्टीथ्रेडिंग: A से Z तक

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

Rust में समवर्तीता और मल्टीथ्रेडिंग: A से Z तक

\n\n

आधुनिक एप्लिकेशन तेजी से मल्टी-कोर प्रोसेसर के कुशल उपयोग की मांग कर रहे हैं। Rust समवर्तीता और मल्टीथ्रेडिंग के लिए एक अनूठा दृष्टिकोण प्रदान करता है, जो संकलन चरण में मेमोरी सुरक्षा की गारंटी के साथ उच्च प्रदर्शन को जोड़ता है। इस लेख में, हम मुख्य अवधारणाओं को समझेंगे: थ्रेड बनाने से लेकर म्यूटेक्स और चैनल के उपयोग तक, व्यावहारिक कोड उदाहरणों के साथ।

\n\n

1. मल्टीथ्रेडिंग की मूल बातें: थ्रेड बनाना और प्रबंधित करना

\n\n

Rust में, थ्रेड मानक लाइब्रेरी std::thread का उपयोग करके बनाए जाते हैं। प्रत्येक थ्रेड स्वतंत्र रूप से निष्पादित होता है, लेकिन अन्य थ्रेड के साथ डेटा साझा कर सकता है।

\n\n

थ्रेड बनाने का एक सरल उदाहरण:

\n\n
use std::thread;\nuse std::time::Duration;\n\nfn main() {\n    let handle = thread::spawn(|| {\n        for i in 1..10 {\n            println!("थ्रेड: संख्या {}", i);\n            thread::sleep(Duration::from_millis(1));\n        }\n    });\n\n    for i in 1..5 {\n        println!("मुख्य थ्रेड: संख्या {}", i);\n        thread::sleep(Duration::from_millis(1));\n    }\n\n    handle.join().unwrap(); // थ्रेड के समाप्त होने की प्रतीक्षा करें\n}
\n\n

मुख्य बिंदु:

\n
    \n
  • thread::spawn एक क्लोजर लेता है जो नए थ्रेड में निष्पादित होता है।
  • \n
  • join विधि वर्तमान थ्रेड को निर्दिष्ट थ्रेड के समाप्त होने तक ब्लॉक करती है।
  • \n
  • join के बिना, मुख्य थ्रेड चाइल्ड थ्रेड से पहले समाप्त हो सकता है।
  • \n
\n\n

थ्रेड के बीच डेटा स्थानांतरित करने के लिए move के साथ क्लोजर का उपयोग करें:

\n\n
use std::thread;\n\nfn main() {\n    let data = vec![1, 2, 3, 4, 5];\n\n    let handle = thread::spawn(move || {\n        println!("थ्रेड से डेटा: {:?}", data);\n    });\n\n    handle.join().unwrap();\n    // println!("{:?}", data); // त्रुटि! data पहले ही स्थानांतरित हो चुका है\n}
\n\n

move कीवर्ड क्लोजर में डेटा का स्वामित्व स्थानांतरित करता है, संकलन चरण में डेटा रेस को रोकता है।

\n\n

2. सुरक्षित डेटा साझाकरण: म्यूटेक्स और लॉक

\n\n

जब कई थ्रेड साझा डेटा तक पहुँचते हैं, तो डेटा रेस का जोखिम होता है। Rust म्यूटेक्स (Mutex) और परमाणु प्रकारों का उपयोग करके इस समस्या का समाधान करता है।

\n\n

Arc (परमाणु संदर्भ काउंटर) के साथ Mutex का उपयोग करने का उदाहरण:

\n\n
use std::sync::{Arc, Mutex};\nuse std::thread;\n\nfn main() {\n    let counter = Arc::new(Mutex::new(0));\n    let mut handles = vec![];\n\n    for _ in 0..10 {\n        let counter = Arc::clone(&counter);\n        let handle = thread::spawn(move || {\n            let mut num = counter.lock().unwrap();\n            *num += 1;\n        });\n        handles.push(handle);\n    }\n\n    for handle in handles {\n        handle.join().unwrap();\n    }\n\n    println!("परिणाम: {}", *counter.lock().unwrap()); // 10\n}
\n\n

महत्वपूर्ण विवरण:

\n
    \n
  • Arc<T> कई थ्रेड को एक ही डेटा का स्वामित्व रखने की अनुमति देता है (परमाणु क्लोनिंग)।
  • \n
  • Mutex::lock() एक लॉक लौटाता है; यदि लॉक पहले से लिया हुआ है, तो थ्रेड प्रतीक्षा करता है।
  • \n
  • स्कोप से बाहर निकलने पर लॉक स्वचालित रूप से जारी हो जाता है।
  • \n
\n\n

अधिक सूक्ष्म नियंत्रण के लिए RwLock का उपयोग करें, जो पाठकों और लेखकों को अलग करता है:

\n\n
use std::sync::RwLock;\n\nlet lock = RwLock::new(5);\n\n// पढ़ना: एक साथ कई थ्रेड\n{\n    let r1 = lock.read().unwrap();\n    let r2 = lock.read().unwrap();\n    println!("पढ़ रहे हैं: {} और {}", r1, r2);\n}\n\n// लिखना: केवल एक थ्रेड\n{\n    let mut w = lock.write().unwrap();\n    *w += 1;\n    println!("लिखा: {}", w);\n}
\n\n

3. संदेश भेजने के लिए चैनल

\n\n

साझा मेमोरी का विकल्प — चैनल का उपयोग करके एक्टर मॉडल। Rust एक मल्टी-प्रोड्यूसर, सिंगल-कंज्यूमर चैनल (mpsc) प्रदान करता है।

\n\n

मूल उदाहरण:

\n\n
u                

ब्लॉग

पुस्तक अनुशंसाएँ