الدرس 12: تسابق البيانات، الجمود (Deadlock) والعمليات الذرّية
يتعمّق هذا الدرس في ثلاثة تهديدات يصعب تصحيحها: data race (بتعريفه الدقيق في C++)، deadlock (خيطان ينتظر كلٌّ منهما الآخر)، والعمليات الذرّية (std::atomic) كبديل خفيف عن mutex للعدّادات البسيطة.
data race = شخصان يكتبان على الورقة نفسها في آنٍ واحد. deadlock = كلٌّ منهما يمسك بما يحتاجه الآخر وينتظر. atomic = عملية غير قابلة للتجزئة — لا يمكن تداخلها.
- data race (تسابق البيانات)
- وفقًا لمعيار C++: خيطان يصلان إلى موقع الذاكرة نفسه، أحدهما على الأقل يكتب، ولا يوجد synchronisation بينهما. يؤدي ذلك إلى undefined behavior.
- السلوك غير المُعرَّف (undefined behavior)
- حالة لا يحدّد فيها معيار C++ ما الذي سيحدث — إذ قد يولّد المترجم أيّ كود، بما في ذلك الأعطال (crashes)، أو قيمًا خاطئة، أو حتى تشغيلًا صحيحًا أحيانًا.
- deadlock (الجمود)
- حالة ينتظر فيها خيطان أو أكثر، كلٌّ منهما أن يحرّر الآخر قفل mutex، فلا يستطيع أيٌّ منها التقدّم أبدًا.
- atomic (ذرّي)
- عملية تُنفَّذ كوحدة غير قابلة للتجزئة. يضمن std::atomic<T> في C++ ألّا يُقاطَع تسلسل read-modify-write بواسطة خيط آخر.
- compare-exchange
- عملية ذرّية تقارن القيمة الحالية بقيمة متوقَّعة؛ فإن تساوتا استبدلتها بقيمة جديدة. وهي أساس خوارزميات lock-free.