اجازه دهید صادقانه بگویم: کد استاد شما "درست" کار نمیکند؛ فقط "ظاهر" کار کردن دارد!
در واقع این کد دچار یک شرایط رقابتی (Race Condition) شده و تنها به این دلیل که استادتان خروجی چند خط اول را دیده، فکر کرده که برنامه سالم اجرا شده است. در ادامه، موشکافانه توضیح میدهم که چرا در لینوکس این اتفاق میافتد و چرا این روش کاملاً اشتباه است.
🧠 دقیقاً در لینوکس چه اتفاقی میافتد؟
- برنامه اصلی (Main) تمام میشود، اما کارگرها را نمیکشد!
وقتی main به دستور print("All processes finished!") میرسد، کار خود را تمام کرده و از تابع خارج میشود. در این لحظه، ۴ پردازش کارگر هنوز مشغول اجرا هستند (چون حلقهی بینهایت دارند). - در لینوکس، فرزندانِ یک پردازشِ مرده، یتیم (Orphan) میشوند
وقتی پردازش اصلی (پدر) تمام میشود، سیستمعامل لینوکس، پردازشهای فرزند را به init (یا systemd با PID=1) میچسباند. پایتون تلاش میکند وقتی خارج میشود، فرزندان را با دستور terminate() بکشد، اما این کار زمانبر است و به صورت ناهمگام (Asynchronous) انجام میشود. پنجرهی زمانی (Time Window) برای چاپ
بین لحظهای که main تمام میشود و لحظهای که سیستمعامل یا Python واقعاً آن ۴ پردازش را از بین میبرد، حدوداً چند میلیثانیه فاصله است. در همین فاصلهی کوتاه، کارگرها موفق میشوند:- اولین آیتم (0) را از صف بردارند.
- ۲ ثانیه بخوابند (time.sleep(2)).
- پیام job 0 completed! را چاپ کنند.
- دوباره به ابتدای حلقه برگردند و آیتم بعدی (1) را بردارند.
- باز هم ۲ ثانیه بخوابند و چاپ کنند.
این چرخه تا جایی ادامه پیدا میکند تا اینکه سیستمعامل فرصت کند و آنها را بکشد. معمولاً تا ۴ یا ۵ آیتم اول را چاپ میکنند قبل از اینکه از بین بروند.