स्विफ्ट में समवर्तीता और मल्टीथ्रेडिंग: उन्नत स्तर
समवर्तीता (concurrency) iOS/macOS डेवलपमेंट में सबसे जटिल और महत्वपूर्ण विषयों में से एक है। उन्नत स्तर पर, Swift शक्तिशाली उपकरण प्रदान करता है: क्लासिक Grand Central Dispatch (GCD) से लेकर आधुनिक async/await मॉडल और सख्त Actors प्रणाली तक। इस लेख में, हम थ्रेड्स को कुशलतापूर्वक प्रबंधित करने, डेटा रेस से बचने और थ्रेड-सुरक्षित कोड लिखने का तरीका समझेंगे।
1. Grand Central Dispatch (GCD): कतारों और समूहों के साथ कार्य
GCD अभी भी Swift में मल्टीथ्रेडिंग का आधार है। हालांकि, उन्नत स्तर पर, केवल main और global() के बीच अंतर को समझना ही नहीं, बल्कि कार्यों की निर्भरताओं को प्रबंधित करने में सक्षम होना भी महत्वपूर्ण है।
स्वयं की कतारें बनाना
let serialQueue = DispatchQueue(label: "com.pythonlib.serial")let concurrentQueue = DispatchQueue(label: "com.pythonlib.concurrent", attributes: .concurrent)
serialQueue.async { print("अनुक्रमिक कतार में कार्य 1")}concurrentQueue.async { print("समानांतर कतार में कार्य 2")}DispatchGroup: एकाधिक कार्यों का सिंक्रनाइज़ेशन
let group = DispatchGroup()let queue = DispatchQueue.global()
queue.async(group: group) { sleep(1) print("डेटा लोड हो रहा है 1")}queue.async(group: group) { sleep(2) print("डेटा लोड हो रहा है 2")}
group.notify(queue: DispatchQueue.main) { print("सभी लोडिंग पूर्ण, UI अपडेट कर रहे हैं")}DispatchGroup का उपयोग करें जब आपको कई समानांतर संचालनों (जैसे, चित्र लोड करना या JSON पार्स करना) के पूरा होने की प्रतीक्षा करनी हो।
2. आधुनिक async/await मॉडल और Task
Swift 5.5 से शुरू होकर, भाषा को async और await कीवर्ड के माध्यम से एसिंक्रोनसी के लिए मूल समर्थन मिला। यह कोड पढ़ने को सरल बनाता है और "क्लोजर के पिरामिड" से बचाता है।
एसिंक्रोनस फ़ंक्शन की घोषणा और कॉल
func fetchUserData() async -> String { // नेटवर्क अनुरोध का अनुकरण try? await Task.sleep(nanoseconds: 2_000_000_000) return "User data loaded"}
Task { let result = await fetchUserData() print(result) // "User data loaded" प्रिंट करेगा}async let के साथ समानांतर कॉल
func loadImage() async -> Data { return Data() }func loadMetadata() async -> String { return "meta" }
Task { async let image = loadImage() async let metadata = loadMetadata() let result = try await (image, metadata) print("चित्र: \\(result.0), मेटाडेटा: \\(result.1)")}async let आपको कई एसिंक्रोनस कार्यों को समानांतर रूप से चलाने और उन सभी की प्रतीक्षा करने की अनुमति देता है। यह अनुक्रमिक कॉल की तुलना में अधिक कुशल है।
3. Actors: भाषा स्तर पर थ्रेड-सुरक्षा
एक्टर (Actors) डेटा रेस से सुरक्षा के लिए एक नया तंत्र है। वे गारंटी देते हैं कि उनकी स्थिति तक पहुंच स्वचालित रूप से सिंक्रनाइज़ होगी।
एक्टर की परिभाषा और उपयोग
actor BankAccount { private var balance: Double = 0.0 func deposit(amount: Double) { balance += amount print("जमा के बाद शेष राशि: \\(balance)") } func withdraw(amount: Double) -> Bool { guard balance >= amount else { return false } balance -= amount return true } func getBalance() -> Double { balance }}
Task { let account = BankAccount() await account.deposit(amount: 100) let success = await account.withdraw(amount: 50) print("निकासी सफल: \\(success)")}एक्टर के सभी तरीके डिफ़ॉल्ट रूप से पृथक होते हैं — उन्हें केवल await के माध्यम से ही कॉल किया जा सकता है। यह कई थ्रेड्स से डेटा में आकस्मिक परिवर्तन को रोकता है।
गैर-पृथक तरीके (nonisolated)
actor Logger { nonisolated func log(message: String) { print("लॉग: \\(message)")\