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

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

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

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

Rust में समवर्तीता और मल्टीथ्रेडिंग: मूल बातों से उन्नत तकनीकों तक



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



1. सुरक्षित मल्टीथ्रेडिंग: Send, Sync और Arc<Mutex<T>>



Rust में सुरक्षित मल्टीथ्रेडिंग का आधार दो प्रमुख ट्रेट्स हैं: Send और Sync। Send को लागू करने वाले प्रकार को थ्रेड्स के बीच सुरक्षित रूप से स्थानांतरित किया जा सकता है। Sync को लागू करने वाले प्रकार को थ्रेड्स के बीच संदर्भ द्वारा सुरक्षित रूप से साझा किया जा सकता है। अधिकांश मानक प्रकार (जैसे, i32, String) स्वचालित रूप से दोनों ट्रेट्स को लागू करते हैं, यदि उनमें केवल Send/Sync डेटा होता है।



एकाधिक थ्रेड्स से परिवर्तनीय डेटा तक साझा पहुँच के लिए, अक्सर Arc<Mutex<T>> पैटर्न का उपयोग किया जाता है। Arc (परमाणु संदर्भ गणक) थ्रेड्स के बीच स्वामित्व साझा करने की अनुमति देता है, और Mutex पारस्परिक बहिष्करण सुनिश्चित करता है।



use std::sync::{Arc, Mutex};use std::thread;

fn main() { let counter = Arc::new(Mutex::new(0)); let mut handles = vec![];

for _ in 0..10 { let counter = Arc::clone(&counter); let handle = thread::spawn(move || { let mut num = counter.lock().unwrap(); *num += 1; }); handles.push(handle); }

for handle in handles { handle.join().unwrap(); }

println!("Result: {}", *counter.lock().unwrap());}


यह याद रखना महत्वपूर्ण है: Rust में Mutex केवल एक लॉक नहीं है, बल्कि एक कंटेनर है जो डेटा की रक्षा करता है। लॉक प्राप्त करने पर एक स्मार्ट पॉइंटर MutexGuard वापस आता है, जो स्कोप से बाहर निकलने पर स्वचालित रूप से लॉक को मुक्त कर देता है। यह क्लासिक "अनलॉक करना भूल गया" त्रुटि को समाप्त करता है।



उन्नत सलाह: Mutex के बजाय RwLock



यदि आपका डेटा अक्सर पढ़ा जाता है, लेकिन शायद ही कभी बदला जाता है, तो RwLock का उपयोग करें। यह कई थ्रेड्स को एक साथ डेटा पढ़ने की अनुमति देता है, लेकिन लेखन को तब तक ब्लॉक करता है जब तक कम से कम एक पाठक मौजूद हो। यह "पाठकों की संख्या लेखकों से अधिक" परिदृश्यों में प्रदर्शन में काफी सुधार कर सकता है।



use std::sync::RwLock;

let data = RwLock::new(vec![1, 2, 3]);

// पढ़ना — कई थ्रेड एक साथ पढ़ सकते हैंlet read_guard = data.read().unwrap();println!("First element: {}", read_guard[0]);drop(read_guard); // स्पष्ट रूप से लॉक जारी करें

// लिखना — विशेष पहुँचlet mut write_guard = data.write().unwrap();write_guard.push(4);


2. चैनल (Channels): थ्रेड्स के बीच संदेश भेजना



चैनल साझा मेमोरी का एक विकल्प हैं। Rust में दो मुख्य प्रकार के चैनल हैं: std::sync::mpsc (मल्टी-प्रोड्यूसर, सिंगल-कंज़्यूमर) और crossbeam-channel (मल्टी-प्रोड्यूसर, मल्टी-कंज़्यूमर)।



मानक mpsc "एक उपभोक्ता - कई उत्पादक" परिदृश्यों के लिए उपयुक्त है। यह एक कतार के सिद्धांत पर काम करता है: भेजने वाले संदेश डालते हैं, प्राप्तकर्ता उन्हें FIFO क्रम में लेता है।



use std::sync::mpsc;use std::thread;

fn main() { let (tx, rx) = mpsc::channel();

let tx1 = tx.clone(); thread::spawn(move || { tx1.send("थ्रेड 1 से संदेश").unwrap(); });

thread::spawn(move || { tx.send("थ्रेड 2 से संदेश").unwrap(); });

for received in rx { println!("प्राप्त: {}", received); }}


ब्लॉग

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