حزمة sync
Sync Package
مفهوم
~22 دقيقة
حزمة sync — Sync Package
القنوات هي الطريقة المفضلة للتزامن في Go، لكن أحياناً تحتاج أدوات منخفضة المستوى. حزمة sync توفر أقفال (mutexes) ومجموعات انتظار وغيرها.
سباق البيانات — Race Condition
قبل أن نتعلم الحلول، لنفهم المشكلة:
main.go
Output:
ملاحظة: في Go Playground قد تحصل على 1000 أحياناً لأن الجدولة تختلف. لكن على جهازك مع
-raceflag ستكتشف المشكلة.
sync.Mutex — القفل المتبادل
Mutex يضمن أن goroutine واحد فقط يصل للمنطقة الحرجة:
main.go
Output:
sync.RWMutex — قفل القراءة/الكتابة
إذا كانت القراءات أكثر بكثير من الكتابات، RWMutex أفضل — يسمح بقراءات متزامنة:
main.go
Output:
sync.WaitGroup — مجموعة الانتظار
أفضل طريقة لانتظار مجموعة goroutines:
main.go
Output:
قواعد WaitGroup:
Add(n)— قبل بدء goroutineDone()— عند انتهاء goroutine (يساويAdd(-1))Wait()— يُعيق حتى العدّاد = 0
sync.Once — تنفيذ مرة واحدة فقط
مفيد للتهيئة التي يجب أن تحدث مرة واحدة فقط:
main.go
Output:
نمط عملي: تجمّع العمال — Worker Pool
main.go
Output:
كشف سباق البيانات — Race Detector
Go تأتي مع كاشف سباق بيانات مدمج:
# تشغيل مع كشف السباق — Run with race detection
go run -race main.go
go test -race ./...
# يكتشف الأخطاء مثل:
# WARNING: DATA RACE
# Write at 0x00c0000b4010 by goroutine 7:
# Previous read at 0x00c0000b4010 by goroutine 6:
استخدمه دائماً أثناء التطوير والاختبار!
متى تستخدم القنوات vs Mutex؟
| استخدم القنوات عندما | استخدم Mutex عندما |
|---|---|
| تمرير ملكية البيانات | حماية حالة مشتركة |
| توزيع مهام | عدّاد أو cache |
| التواصل بين goroutines | قراءة/كتابة بسيطة |
تحدي — Challenge
استخدم sync.Mutex و sync.WaitGroup لزيادة عدّاد بأمان من 100 goroutine كل واحد يزيده 100 مرة