في مقتطف التعليمات البرمجية هذا، يتم تشغيل goroutine ويزيد بشكل متكرر المتغير i:
package main
import "time"
func main() {
i := 1
go func() {
for {
i
}
}()
ومع ذلك، فإن الإخراج دائمًا هو 1. يمكن أن يعزى هذا السلوك إلى نموذج ذاكرة Go والتنفيذ المحدد لهذا الرمز.
نموذج ذاكرة Go
يحدد نموذج ذاكرة Go الشروط التي بموجبها يمكن ضمان قراءات متغير في goroutine واحد لمراقبة القيم الناتجة عن الكتابة إلى نفس المتغير في goroutine مختلف. ويؤكد على أهمية المزامنة للوصول المتزامن إلى البيانات المشتركة.
حذف المزامنة
في الكود المحدد:
- التعيين إلى i (أي، i ) لا يتبعه أي حدث مزامنة، مما يشير إلى أن التغييرات قد لا تكون مرئية على الفور لـ goroutines الأخرى.
- قد يقوم المترجم بتحسين تحسين الحلقة هذه عن طريق تبسيطها إلى عدم التشغيل.
]التحسين بواسطة المترجم
قد يقوم المترجم العدواني بحذف عبارة i، مما يقلل بشكل فعال من goroutine إلى:
for {}
مثال مع المزامنة
لإثبات أن المشكلة تنبع من عدم المزامنة، ضع في اعتبارك الكود التالي:
package main
import (
"sync"
"time"
)
func main() {
mx := new(sync.Mutex)
i := 1
go func() {
for {
mx.Lock()
i
mx.Unlock()
}
}()
في هذه الحالة، لم يعد الناتج 1، بل رقم كبير، كما هو متوقع. يوفر sync.Mutex المزامنة ويضمن وصول كلا goroutines إلى i بطريقة خاضعة للرقابة، مما يسمح لـ goroutine بزيادة i وجعل التغييرات مرئية للروتين الرئيسي.
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3