البرمجة

التساير في لغة جو: فعّالية التنفيذ المتزامن

في لغة البرمجة جو (Go)، تُعتبر ميزة التساير (Concurrency) أحد الجوانب البارزة التي تميز اللغة وتجعلها قوية في التعامل مع العمليات المتزامنة والتواصل بينها. يعتمد تصميم جو على مفهوم التساير عبر القنوات (Concurrency via Channels)، وهو يوفر آلية فعّالة لتنفيذ عدة دوال بشكل موازي. دعنا نستكشف كيف يمكن تحقيق ذلك بشكل مفصل.

في جو، يُستخدم المصطلح “goroutine” للإشارة إلى التنفيذ الموازي لدوال معينة. يمكنك إنشاء goroutines بسهولة باستخدام كلمة الرئيسية “go” متبوعة بالدالة التي ترغب في تنفيذها. على سبيل المثال:

go
package main import ( "fmt" "time" ) func worker(id int, jobs <-chan int, results chan<- int) { for job := range jobs { fmt.Println("Worker", id, "started job", job) time.Sleep(time.Second) // تمثيل عمل طويل الأمد fmt.Println("Worker", id, "finished job", job) results <- job * 2 } } func main() { const numJobs = 5 jobs := make(chan int, numJobs) results := make(chan int, numJobs) // إنشاء الأعمال for j := 1; j <= numJobs; j++ { jobs <- j } close(jobs) // إطلاق الأعمال بواسطة الـ goroutines for w := 1; w <= 3; w++ { go worker(w, jobs, results) } // جمع النتائج for a := 1; a <= numJobs; a++ { <-results } }

في هذا المثال، يتم إنشاء قناتين، قناة jobs لإرسال الأعمال إلى الـ goroutines وقناة results لاستقبال النتائج منها. يتم إطلاق الـ goroutines باستخدام دالة worker التي تستقبل الوظائف من jobs وترسل النتائج إلى results.

تجنب النسيان في الكود أن نقوم بإغلاق قناة jobs بعد إرسال جميع الأعمال، وذلك لإعلام الـ goroutines بأنه لا يوجد المزيد من الأعمال المتوقعة.

يُظهر هذا المثال كيف يمكنك تحقيق تساير العمليات بسهولة في جو، وذلك من خلال إنشاء وإطلاق goroutines لتنفيذ الوظائف بشكل متزامن.

المزيد من المعلومات

بالطبع، دعونا نعمق أكثر في ميزة التساير في لغة جو ونسلط الضوء على بعض الجوانب الهامة:

  1. القنوات (Channels): في المثال السابق، استخدمنا قنوات لتسهيل تبادل البيانات بين الـ goroutines. قناة jobs استُخدمت لإرسال الأعمال إلى الـ goroutines، في حين استُخدمت قناة results لاستقبال النتائج منها. القنوات تُستخدم لتحقيق التواصل الآمن والفعّال بين الـ goroutines.

  2. التحكم في التنفيذ (Select): جو يوفر تعليمة select التي تسمح لك باختيار العملية التي تحدث أولاً بين عدة قنوات. هذا يفيد في التحكم في تسلسل التنفيذ وتنظيم التواصل بين الـ goroutines.

  3. تنظيم الانتظار (Wait Groups): في البرامج المتزامنة، يمكن أن يكون من الضروري الانتظار حتى يكتمل تنفيذ جميع الـ goroutines قبل استكمال البرنامج الرئيسي. تُستخدم مجموعات الانتظار (Wait Groups) في جو لتحقيق هذا الهدف.

go
package main import ( "fmt" "sync" "time" ) func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) { defer wg.Done() // تنبيه المجموعة بانتهاء الـ goroutine for job := range jobs { fmt.Println("Worker", id, "started job", job) time.Sleep(time.Second) fmt.Println("Worker", id, "finished job", job) results <- job * 2 } } func main() { const numJobs = 5 jobs := make(chan int, numJobs) results := make(chan int, numJobs) var wg sync.WaitGroup // إنشاء الأعمال for j := 1; j <= numJobs; j++ { jobs <- j } close(jobs) // إطلاق الأعمال بواسطة الـ goroutines for w := 1; w <= 3; w++ { wg.Add(1) // إشارة ببدء goroutine جديدة go worker(w, jobs, results, &wg) } // إغلاق القناة results عند انتهاء كل الـ goroutines go func() { wg.Wait() // انتظار انتهاء جميع الـ goroutines close(results) }() // جمع النتائج for result := range results { fmt.Println("Result:", result) } }

هذا المثال يستخدم sync.WaitGroup لضمان انتظار انتهاء جميع الـ goroutines قبل إغلاق قناة النتائج واستكمال البرنامج الرئيسي.

باستخدام هذه الميزات، يمكنك تنظيم تنفيذ البرامج التي تستفيد من فعّالية التساير في جو والتي تتيح لك الاستفادة القصوى من المتعدد المهام.

زر الذهاب إلى الأعلى