מנעול (תוכנה)

בתוכנה, מנעול הוא מנגנון סנכרון לכפיית מגבלות על הגישה למשאב בסביבה בה יש תהליכונים (Threads) רבים. מנעולים הם דרך לאכוף מדיניות בקרת מקביליות מסוימת.

מטרת המנעול היא למנוע התנגשויות בין התהליכונים ומצב של מרוץ תהליכים שעלול לגרום לתוצאות שגויות ובלתי צפויות. השימוש במנעול פוגע במקביליות ובביצועים, ולכן יש להשתמש במנעולים רק בנקודות הכרחיות ולצמצם את אזור הנעילה – הקטע הקריטי, סביב קטע קוד קצר ככל האפשר.

דרך פעולה
בעת הגעה לקטע קריטי, מבקש התהליכון לבצע נעילה. במידה והמנעול פנוי, הנעילה תצליח והתהליכון יוכל להתקדם. בשלב זה, כל תהליכון אחר שיגיע לקטע הקריטי ויבקש לבצע נעילה - יאלץ להמתין עד לשחרור המנעול על ידי התהליכון הנועל (בקשת הנעילה היא פעולה חוסמת). עם יציאת התהליכון הנועל מהקטע הקריטי, הוא יבצע שחרור של המנעול, ותהליכון אחר שביקש לבצע נעילה יצליח בנעילה ויכנס לקטע הקריטי.

ישנם שני  סוגי מימוש למנעול, מנעול הוגן בו כל מי שמבקש לבצע נעילה נכנס לתור המתנה ומתקדם לפי מיקומו בתור, ומנעול לא הוגן שבו באופן לא צפוי מתקבלת ההחלטה מי ישתחרר, דבר שעלול לגרום להרעבה אם מישהו מחכה אך כל פעם לפני שמישהו יוצא מהקטע הקריטי מישהו חדש מנסה לשחרר את המנעול ומקבל קדימות על פני האחר.

דוגמה לשימוש
להמחשת הצורך במנעול, נסתכל על הפשטה של הפקודות שמרכיבות את פעולת ההגדלה ב-1 של ערך בזיכרון (increment):
 התהליכון קורא מהזיכרון את הערך שבמקום X
 התהליכון מגדיל את הערך ב-1
 התהליכון כותב למקום X את הערך החדש

כעת נסתכל על 2 תהליכונים שמבצעים פעולת הגדלה על אותו מקום בזיכרון (כדי להבהיר את הבעייתיות, נפרט את פעולת ה increment לפקודות המרכיבות אותה).

תרחיש ראשון: ללא שימוש במנעול (תוצאה שגויה)
 תהליכון א' קורא מהזיכרון את הערך שבמקום X
 תהליכון א' מגדיל את הערך ב-1
 תהליכון ב' קורא מהזיכרון את הערך שבמקום X
 תהליכון ב' מגדיל את הערך ב-1
 תהליכון ב' כותב למקום X את הערך החדש
 תהליכון א' כותב למקום X את הערך החדש
הערך גדל לבסוף רק פעם אחת: השינוי שביצע תהליכון ב' נדרס על ידי הכתיבה לזיכרון של תהליכון א'. לכן, בסביבה עם תהליכונים רבים החולקים זיכרון, פעולת ה- increment צריכה להיות מוגנת על ידי מנעול.

תרחיש שני: שימוש במנעול: (תוצאה תקינה)
 תהליכון א' מבצע נעילה
 תהליכון א' קורא מהזיכרון את הערך שבמקום X
 תהליכון א' מגדיל את הערך ב-1
 תהליכון א' כותב למקום X את הערך החדש
 תהליכון א' מבצע שחרור
 תהליכון ב' מבצע נעילה
 תהליכון ב' קורא מהזיכרון את הערך שבמקום X
 תהליכון ב' מגדיל את הערך ב-1
 תהליכון ב' כותב למקום X את הערך החדש
 תהליכון ב' מבצע שחרור
השימוש במנעול פתר את השגיאה שנוצרה והביא לתוצאה הרצויה, אך גם מנע את המקביליות (תהליכון ב' לא יכול לבצע נעילה עד שתהליכון א' ביצע שחרור) ולכן פגע בביצועים.

ראו גם
פעולה אטומית

הערות שוליים

תהליכים (מדעי המחשב)