التزامن وتعدد الخيوط في Swift: تقنيات متقدمة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

التزامن وتعدد الخيوط في Swift: مستوى متقدم

التزامن (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("اكتملت جميع التحميلات، نقوم بتحديث واجهة المستخدم")}

استخدم 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 "تم تحميل بيانات المستخدم"}

Task { let result = await fetchUserData() print(result) // سيتم طباعة "تم تحميل بيانات المستخدم"}

استدعاءات متوازية باستخدام 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)")\                

المدونات

توصيات الكتب