وظيفة الإلحاق: ليست آمنة لمؤشر الترابط للوصول المتزامن
عند استخدام goroutines بشكل متزامن لإلحاق عناصر بشريحة داخل حلقة for، تحدث حالات شاذة في البيانات يمكن أن تنشأ. قد تظهر البيانات المفقودة أو الفارغة في الشريحة الناتجة، مما يشير إلى سباقات البيانات المحتملة.
يحدث هذا لأنه في Go، لا توجد قيمة آمنة بشكل طبيعي للقراءة والكتابة المتزامنة. الشرائح، التي يتم تمثيلها برؤوس الشرائح، ليست استثناءً. يعرض الكود المقدم سباقات البيانات بسبب الوصول المتزامن:
destSlice := make([]myClass, 0) var wg sync.WaitGroup for _, myObject := range sourceSlice { wg.Add(1) go func(closureMyObject myClass) { defer wg.Done() var tmpObj myClass tmpObj.AttributeName = closureMyObject.AttributeName destSlice = append(destSlice, tmpObj) }(myObject) } wg.Wait()
للتحقق من وجود سباقات البيانات، قم بتنفيذ الأمر التالي:
go run -race play.go
سوف ينبهك الإخراج إلى البيانات السباقات:
WARNING: DATA RACE ...
حل مشكلات التزامن
لحل هذه المشكلة، قم بحماية حق الوصول للكتابة إلى destSlice عن طريق استخدام المزامنة.Mutex:
var ( mu = &sync.Mutex{} destSlice = make([]myClass, 0) ) var wg sync.WaitGroup for _, myObject := range sourceSlice { wg.Add(1) go func(closureMyObject myClass) { defer wg.Done() var tmpObj myClass tmpObj.AttributeName = closureMyObject.AttributeName mu.Lock() destSlice = append(destSlice, tmpObj) mu.Unlock() }(myObject) } wg.Wait()
بدلاً من ذلك، فكر في استخدام قناة للتعامل بشكل غير متزامن مع الملحقات:
var ( appendChan = make(chan myClass) destSlice = make([]myClass, 0) ) var wg sync.WaitGroup for _, myObject := range sourceSlice { wg.Add(1) go func(closureMyObject myClass) { defer wg.Done() var tmpObj myClass tmpObj.AttributeName = closureMyObject.AttributeName appendChan
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3