اكيد عدي علينا مصطلح ال Multithreading ده كتير .. ايه هو بقي؟
ال Multithreading يعني إنك تخلي التطبيق بتاعك يقدر ينفذ أكتر من task علي اكتر من thread عشان يكون أسرع وأكثر كفاءة.
يعني تخيل معايا ان ال screen بتاعتك محتاج تظبط فيها UI ومحتاج تعمل call ل API ومحتاج تعمل processing علي حاجه معينه، لو الحاجات دي عملتها ورا بعض (بشكل متزامن او Syncronous) علي نفس ال thread واللي هتكون ال main thread التطبيق هيكون بطئ واوقات ممكن يحصله freez، وهنا ظهر الاحتياج لل Multithreading وانك تقسم ال tasks بتاعتك علي اكتر من thread فتقلل الوقت وتستغل كل ال resources بتاعتك
هاخدك لحتة سريعا كده ونرجع تاني..
لما التطبيق بتاعك يبدأ يشتغل ال Operating system(OS) بيعمله حاجه اسمها Thread Pool (خاصة لكل تطبيق علي حده مش بتكون shared) ودي بيبقي فيها شوية threads جاهزة للتطبيق انه يستخدمها بدل ماا تحتاج انت ت create اي thread وانت بتشتغل
ال OS هو اللي بي handle ال pool دي تماما يعني لو ال tasks بتاعتك كتير ممكن يزود threads مؤقتا ولو قليل ممكن يقلل او يوقف شوية threads وده طبيعي لانه هو اللي عارف ايه متاح من ال CPU وال Memory وعارف التطبيقات التانيه بتستهلك ايه.
دلوقتي انت معاك ال thread pool بتاعتك، وعندك كذا task عاوز تقسمهم علي اكتر من thread عشان التطبيق بتاعك يكون اسرع وكفاءته اعلي وبالتالي المستخدم يكمل معاك حبه اكتر. هنحتاج بقي tools عشان نتعامل مع ال threads الجاهزه دي ، يعني حاجه تساعدني اقول ان عاوز ال task دي في thread لوحدها وال OS يتعامل بقي مع ال thread pool ويعمل assign ولما ال task تخلص يرجع تاني ال thread لل pool
اغلب الاجهزه حاليا فيها كذا core عشان ال tasks تشتغل مع بعض بشكل متوازي حقيقي ، انت تقدر تشتغل علي اكتر من thread علي core واحد عادي بس التوازي بين التاسكات مش هيكون حقيقي ، في الواقع اللي بيحصل حاجه اسمها slicing يعني ال CPU بيدي فترة زمنيه معينه لكل task إنها تنفذ شغلها ولما الفتره دي تخلص بيروح ل thread تانيه عشان تشتغل علي ال task بتاعتها ، طبعا ده بيحصل بشكل سريع يحسسك انه كأن ال tasks شغاله مع بعض parrallel بس ده مش حقيقي ، ال Multi-cores بقي هو اللي بيحقق ال parallel execution بشكل حقيقي
طبعا انت برضه مش هتقول هتشتغل علي Core ولا اكتر انما ال OS هو اللي هيشغل ال threads المختلفه من ال pool علي ال cores المتاحه
احنا كده فهمنا ان فيه Threads جوا Pool ،احنا محتاجين Tools عشان نتعامل مع ال Threads دي فايه هي بقي ال Tools دي اللي انا هستخدمها ك Developer.
GCD (Grand Central Dispatch)
هي ال API الفعلية اللي بتديهالي Foundation عشان اتعامل مع ال Multithreading.
في بقي abstraction layers و frameworks مبنيه عليها بتساعدني اعمل شوية عمليات بشكل اسهل وكود ابسط وهما
OperationQueue
Async/Await
Combine
RxSwift
ودول مش directly بيتعاملو مع ال Multithreading، لا هما بيستخدمو abstraction layer بتتعامل مع ال GCD API
GCD (Grand Central Dispatch)
زي ما قلنا هي ال API اللي بتساعدني في إدارة ال tasks اللي عايزاها تتنفذ في ال background أو بشكل متوازي concurrent او متسلسل serial زي ما احب، وبتوفرمجموعة من ال functions تساعدني اوزع ال tasks علی multiple threads بشكل ذكي.
ايه بقي اللي بتديهولي ال API دي ؟
هي بتديني DispachQueues كل واحده منهم بتشتغل علي ال tasks بطريقه معينه ، ال Queues دي هي اللي بتديني ال low level control لل tasks.
أنواع Queues في GCD:
١- Serial Queue (قائمة انتظار تسلسلية):
بتنفذ ال tasks واحده ورا التانيه بترتيب FIFO(First in first out) وبيكون في task واحده بس بتتنفذ في الوقت الواحد
في منها نوع خاص وهو
ال Main Queue:
وده ال Queue الوحيد اللي بيتعامل مع ال UI وال Tasks فيه بتتنفذ في ال Main thread
٢- Concurrent Queue (قائمة انتظار متوازية):
بتنفذ اكتر من task في نفس الوقت، يعني ممكن يشتغلو كلهم بشكل متوازي ، وليه بقول ممكن لان ال OS او النظام هو اللي بيحدد كام task ممكن تشتغل بالتوازي علي حسب ال resources المتاحة
طيب انا كده عرفت انواع ال Queues محتاجة اعرف بقي ازاي ال tasks بتشتغل في ال Queues دي فهنروح ل
أنواع ال Methods مع Queues
١- Async (Asynchronous)
تنفذ الtask بشكل غير متزامن، يعني ال code مش هيستنی لحد ما ال task دي تخلص (non-blocking) يعني الكود اللي بعدها هيشتغل عادي.
٢- Sync (Synchronous):
بتنفذ الtask بشكل متزامن، يعني ال code هيستني لحد ما ال task تخلص(blocking) يعني الكود اللي بعدها هيستني.
انا هكتب شوية امثله عشان تفهمني اكتر بس قبل ما اكتبها هوضح ازاي بن create ال DispachQueues
هو مبدأيا في انواع جاهزه وفي Cusom انا بعملها create خلينا نتكلم عنهم
ال Main Queue
وده serial queue جاهز بينفذ ال tasks في ال main thread
هنا ياريت نركز شوية انا ليه اديت مثال ب async مش ب sync
لان انا هنا في ال Main Queue اللي بيشتغل علي ال Main thread اللي مينفعش تعطل عشان ميحصلش freeze لل app فطبيعي ان هستخدم ال async
طيب هيحصل ايه لو استخدمت sync؟ هيحصل deadlock .. طيب يعني ايه؟ نركزززززز
لو انا اصلا مش بعمل multithreading فالكود بتاعي طبيعي بيتنفذ ف ال main thread..تمام؟
طيب انا دلوقتي شغاله في ال main thread ورحت استخدمت ال main queue مع sync فكدة ال main thread هتبقي واقفه مستنيه الكود اللي بين القوسين يتنفذ، بس الكود اللي بين القوسين محتاج اصلا ال main thread عشان يتنفذ فكده ال main thread هتبقي مستنيه نفسها .. وهتفضل مستنيه بقي وده اسمه deadlock
طيب امتي استخدم sync مع ال main queue؟
لو كنت في thread تانيه غير ال main .. ياريت نقرا الجزء ده تاني براحه
ال Global Queues
ودول ٤ جاهزين نوعهم Concurrent بتديهوملي GCD من غير ما احتاج اعرفهم ب label او احجزلهم Queue بديهم بس حاجه اسمها qos (Quality of Service) عشان احدد ال Queue انهي واحده من ال ٤ واللي بيختلفو في الأولوية واللي هما
اقصي اولوية User Interactive
ودي لل tasks اللي لازم تتنفذ علي طول زي ال tasks اللي بتعمل update لل UI او اللي بتستجيب ل action من ال user زي انه يضغط زرار مثلا
تاني اولوية User Initiated
ودي لل tasks اللي بيستناها ال user زي مثلا ان اعمل call ل api او اقرا file صغير
تالت اولوية Utility
ودي لل tasks اللي ممكن تاخد وقت طويل نسبيا زي تحميل فايل مثلا
آخر اولوية Background
دي للحاجات اللي عادي تاخد وقتها براحتها زي ان اقرا فايل كبير مثلا او اعمل backup
بس هنا انا عاوزه اقول ملحوظه مهمه احنا هنا بنتعامل مع concurrent queues يعني ترتيب ال tasks مش مضمون حسب ال OS هيوزع ال threads ازاي بس ال qos بتدي بس hint عن الاولويه في حالة لو ال OS كان محتاج ياخد قرار يعمل مين الاول لو ال resources كانت قليلة
ولو مقلتش ال qos ومحطتش ال parameter ده فهو هيبقي في ال default وهنا ال task هتشتغل علي اي queue متاح حسب الظروف والنظام علي الاغلب بيختار بين userInitiated و utility
ال Custom Queue
هنا بقي انا ب create queue وبحطله اسم وبحدد نوعه
كده انا عرفت serial queue، طب ازاي؟ هقولك لانه هو ال default، فكل اللي بحتاجه ان ادي بس اسم لل queue ده من خلال ال label
طيب لو حبيت اخليه concurrent بزود parameter اسمه attributes وبقوله ان النوع concurrent
واقدر كمان احدد ال qos ليه
ولو غيرت ال qos للتاسك اللي هعملها assign علي ال queue فهي هتعمل override لل qos اللي اديتها لل queue نفسه
خليني بقي اقولك امثله لانواع ال Queues مع ال Methods
Serial Queue مع Async:
ال tasks اللي اتضافت لل queue هتتنفذ واحده واحده FIFO عشان هو serial queue لكن الكود اللي بعدهم مش هيتعطل عشان مستخدمين async
Serial Queue مع Sync:
ال tasks اللي اتضافت لل queue هتتنفذ واحده واحده FIFO عشان هو serial queue لكن الكود اللي بعدهم هيتعطل عشان مستخدمين sync وهيتنفذ بعد ما ال tasks تخلص
Concurrent Queue مع Async:
ال tasks ممكن تشتغل بالتوازي، والـ code بعدهم مش هيستني لكن ترتيب نتيجة ال tasks مش مضمون وممكن يحصل حاجه اسمها race condition: يعني انا معتمده علي نتيجة نهائيه بتحصل بترتيب احداث معينه فلو الاحداث دي حاجه منها تمت قبل التانيه النتيجه النهائيه مش هتكون سليمه
Concurrent Queue مع Sync:
دي حالة خلت ال concurrent queue مالوش لازمة لان sync بتعمل block فال tasks هتتم واحده ورا التانيه ومش هيستفيدوا من التوازي.
بكده انا خلصت اول جزء وهتكلم في Part 2 عن شوية controls زي ال DispatchGroup وال DispatchSemaphore وهتكلم عن باقي ال tools اللي قلت إنها بتستخدم abstraction layer لو حبيت تقراهم تقدر تعمل subscribe عشان يجيلك mail بيهم
ي ريت البوست بتاعك يبقى كل يوم الصبح مثلا يبقى الواحد متعود انه يقرأة وهو رايح الشغل يبقى حاجه ممتازه
ويبقى ال سلوجن هنا swift. والله بحيْيِّكِ علي مجهودك