סנכרון תהליכים וחוטים Process and Thread Synchronization חלק ראשון 1 אלן אזאגורי © מרץ 2002 נושאים מוטיבציה הגדרות פיתרון כללי מנעולים ותמיכתם בחומרה עמוד 2 אלן אזאגורי © מרץ.
Download
Report
Transcript סנכרון תהליכים וחוטים Process and Thread Synchronization חלק ראשון 1 אלן אזאגורי © מרץ 2002 נושאים מוטיבציה הגדרות פיתרון כללי מנעולים ותמיכתם בחומרה עמוד 2 אלן אזאגורי © מרץ.
סנכרון תהליכים וחוטים
Process and Thread
Synchronization
חלק ראשון
1
אלן אזאגורי ©
מרץ 2002
נושאים
מוטיבציה
הגדרות
פיתרון כללי
מנעולים ותמיכתם בחומרה
עמוד 2
אלן אזאגורי ©
מרץ 2002
מוטיבציה
int c = 0; // Global variable
Thread B:
)while (c > -10
;c = c - 1
;kill A
;”print “B wins
Thread A:
)while (c < 10
;c = c + 1
;kill B
;”print “A wins
הנחות
– קריאה/כתיבה של משתנה היא אטומית
– פעולה אריתמטית על המשתנה אינה אטומית
מי זוכה?
האם תמיד יש זוכה?
האם שניהם עשויים
לזכות?
עמוד 3
לפעמים Aולפעמים B
לא
כן ,כאשר הפקודה killאסינכרונית
אלן אזאגורי ©
מרץ 2002
בעית יצרן/צרכן
הגדרות
– שני חוטים (יצרן וצרכן) רצים באותו מרחב זיכרון
– מערך חסום (מעגלי) מכיל את העצמים המיוצרים
– ליצרן מצביע ) (ppלמקום הפנוי הבא במערך
– לצרכן מצביע ) (cpלמקום הבא המכיל את העצם המוכן
הבא
– מספר העצמים המוכנים הוא c
n-1
c
0
cp
עמוד 4
pp
אלן אזאגורי ©
מרץ 2002
)צרכן (המשך/בעית יצרן
int c = 0; // Global variable
Producer:
repeat
while (c>=n) nop;
buf[pp] = new item;
pp = (pp+1) mod n;
c = c + 1;
until false;
Consumer:
repeat
while (c<1) nop;
consume buf[cp];
cp = (cp+1) mod n;
c = c - 1;
until false;
בעיות
c – עדכון בו זמנית (לא מוגן) של
יכול להיות גבוה (נמוך) מן הערך הנכוןc – לכן ערכו של
2002 מרץ
© אלן אזאגורי
5 עמוד
בעית החלב
את/ה:
מסתכל במקרר
הולך לסופר
קונה חלב
חוזר הביתה
מכניס חלב למקרר
שותף:
מסתכל במקרר
הולך לסופר
קונה חלב
חוזר הביתה
מכניס חלב למקרר
בעיה :יותר מדי חלב!
עמוד 6
אלן אזאגורי ©
מרץ 2002
בעית החלב
פיתרון 1
פיתרון :להשאיר פיתקה
מסתכל במקרר
אם אין חלב
אם אין פתקה
השאר פתקה
קנה חלב
הורד פתקה
בעיה :כל אחד קפץ לחדר לכתוב פתק ולא שם לב
לכך שהשני השאיר פתק
עמוד 7
אלן אזאגורי ©
מרץ 2002
בעית החלב
2 פיתרון
בודקים האם גם, לאחר השארת הפיתקה: פיתרון
השותף השאיר פיתקה
Thread A:
leave note A
if (no note B) then
if (no milk) then
buy milk
remove note A
Thread B:
leave note B
if (no note A) then
if (no milk) then
buy milk
remove note B
! קיים תסריט בו אף אחד לא יקנה חלב: בעיה
2002 מרץ
© אלן אזאגורי
8 עמוד
בעית החלב
3 פיתרון
שבירת הסימטריה:פיתרון
Thread A:
Thread B:
leave note A
leave note B
X:while (note B) do nop
Y:if (no note A) then
if (no milk) then
if (no milk) then
buy milk
buy milk
remove note A
remove note B
! יקנה חלבA ,)במקרה של "תחרות" (שניהם משאירים פתק בו זמנית
חסרונות
– רק לשני תהליכים
– לא הוגן
2002 מרץ
© אלן אזאגורי
9 עמוד
הגדרות
מרוץ )(Race Condition
– בד"כ התכנית (המקבילית) עובדת נכון
– קיים תסריט בו התכנית לא עובדת נכון
• לרוב בגלל שבירה איזושהי הנחת אטומיות שאינה
מתקיימת
בדוגמת בעית החלב
– השארת פיתקה
– בדיקה האם השותף השאיר פיתקה
עמוד 10
אלן אזאגורי ©
מרץ 2002
הגדרות (המשך)
מניעה הדדית – mutual exclusion
– מנגנונים המבטיחים שרק חוט אחד מבצע סדרת
פעולות מסוימות בזמן נתון
• אטומיות ביחס לחוטים אחרים
קטע קריטי – critical section
– קטע קוד שרק חוט אחד מבצע בזמן נתון
קריטי
לא קריטי
עמוד 11
אלן אזאגורי ©
יציאה
מרץ 2002
הגדרות (המשך)
אטומיות – Atomicity
– בביצוע סדרת פקודות ע"י חוט אחד,חוטים אחרים אינם
יכולים לראות תוצאות חלקיות -סדרת הפקודות נראית כמו
פעולה אחת שאיננה ניתנת לחלוקה ("פעולה אטומית")
– ניתן להשיג בעזרת מנגנון של מניעה הדדית
דוגמא
– העברת כספים מחשבון לחשבון
Thread B:
)if (account1+account2<min
… then
Thread A:
;account1:= account1 – sum
;account2:= account2 + sum
– לא נאפשר לחוטים אחרים לראות מצב בו הכסף נמשך
מחשבון א' אך לא הגיע לחשבון ב'
עמוד 12
אלן אזאגורי ©
מרץ 2002
תכונות של פתרון לבעיית הקטע
הקריטי
חובה
– רק חוט אחד בקטע קריטי (מניעה הדדית)
– אם יש בקשות להיכנס לקטע קריטי ,אזי חוט אחד ייכנס (אין
קיפאון – )deadlock
רצוי
– חוט המבקש להיכנס לקטע קריטי בסופו של דבר יצליח (אין
הרעבה – )starvation
– עבור כל זוג חוטים ,אם הם יתחרו nפעמים להיכנס לקטע
קריטי ,הם יזכו מספר דומה של פעמים )(fairness
עמוד 13
אלן אזאגורי ©
מרץ 2002
(bakery) אלגוריתם קופת חולים
(1) לפיתרון בעית הקטע הקריטי
שימוש במספרים
– חוט נכנס לוקח מספר
– חוט שמספרו הקטן ביותר נכנס לקטע הקריטי
ניסיון ראשון
Thread i:
initially number[i]=0
number[i]=max{number[1],…,number[n]}+1;
for all ji do
wait until number[j]=0 or (number[j]>number[i])
critical section
number[i]=0 // Exit critical section
2002 מרץ
© אלן אזאגורי
14 עמוד
אלגוריתם קופת חולים )(bakery
לפיתרון בעית מניעה הדדית )(1
בעיה
– חוט iו j-קוראים את המערך בו זמנית
– שניהם "בוחרים" את אותו מספר
קיפאון!
עמוד 15
אלן אזאגורי ©
מרץ 2002
(bakery) אלגוריתם קופת חולים
(2) לפיתרון בעית מניעה הדדית
נשתמש במס' הזהות של התהליך כדי לשבור
סימטריה
Thread i:
initially number[i]=0
number[i]=max{number[1],…,number[n]}+1;
for all ji do
wait until number[j]=0 or
()number[j],j)>(number[i],i)) // lexicographical
// comparison
critical section
number[i]=0 // Exit critical section
2002 מרץ
© אלן אזאגורי
16 עמוד
אלגוריתם קופת חולים )(bakery
לפיתרון בעית מניעה הדדית )(2
בעיה
– חוט iו j-קוראים את המערך בו זמנית )(i>j
– חוט iכותב את המספר ,בודק את ערכו כנגד
numberונכנס לקטע הקריטי (] number[jעדיין )!0
– חוט jממשיך וגם הוא נכנס לקטע הקריטי!
אין מניעה הדדית!
– התהליך עם מספר זהות גבוה ) (iמזדרז להיכנס
לקטע הקריטי לפני ש j-הספיק לכתוב את ]number[j
עמוד 17
אלן אזאגורי ©
מרץ 2002
(bakery) אלגוריתם קופת חולים
(3) לפיתרון בעית מניעה הדדית
נוודא שאין חוטים באמצע בחירת מספר לפני
ההשוואות
ביצוע
Thread i:
initially number[i]=0
choosing[i]=true
number[i]=max{number[1],…,number[n]}+1;
choosing[i]=false
for all ji do
wait until choosing[j]=false
for all ji do
wait until number[j]=0 or
()number[j],j)>(number[i],i))
critical section
number[i]=0 // Exit critical section
2002 מרץ
© אלן אזאגורי
18 עמוד
אלגוריתם קופת חולים )(bakery
לפיתרון בעית מניעה הדדית )(3
אין הרעבה (ולכן אין קיפאון) והפתרון הוגן
– הוכחה בתרגול
פיתרון מסורבל
– הרבה פעולות ,הרבה משתנים
הפיתרון לא יעבוד בסביבות מרובות מעבדים
– Out of order execution
קיימים אלגוריתמים אחרים
בהמשך נלמד על פתרונות אחרים
עמוד 19
אלן אזאגורי ©
מרץ 2002
מנעולים )(locks
מבטיחים גישה בלעדית למידע באמצעות
שתי פונקציות
– ) – lock_acquire(lockפעולה חוסמת (אם
המנעול תפוס)
– ) – lock_release (lockמשחרר את המנעול
עמוד 20
אלן אזאגורי ©
מרץ 2002
( – דוגמאlocks) מנעולים
צרכן/ דוגמא – בעית יצרן
Producer:
repeat
while (c>n) nop;
buf[pp] = new item;
pp = (pp+1) mod n;
lock_acquire(c_lock)
c = c + 1;
lock_release(c_lock)
until false;
Consumer:
repeat
while (c<1) nop;
consume buf[cp];
cp = (cp+1) mod n;
lock_acquire(c_lock)
c = c - 1;
lock_release(c_lock)
until false;
?while- בc האם מספיק להגן רק על שינוי
?– מה קורה במקרה של יותר מצרכן אחד
2002 מרץ
© אלן אזאגורי
21 עמוד
מימוש מנעולים
lock_release(L):
)(disableInterrupts
L := FREE
)(enableInterrupts
אטומיות
– מובטחת ע"י חסימת פסיקות
lock_acquire(L):
)(disableInterrupts
while LFREE do
)(enableInterrupts
)(disableInterrupts
L := BUSY
)(enableInterrupts
Busy wait
– ניתן למנוע ע"י ניהול תור החוטים המחכים
למה חשוב לאפשר פסיקות בתוך הלולאה?
ומה קורה במערכות מרובות מעבדים?
– חסימת פסיקות אינה מבטיחה אטומיות...
– דורש תמיכה מהחומרה לפקודות "חזקות" יותר
עמוד 22
אלן אזאגורי ©
מרץ 2002
מימוש מנעולים
test&set תמיכת חומרה
test&set(boolvar)
והחזר ערך קודםtrue – כתוב ערך
lock_acquire(L):
while test&set(L)
do nop
lock_release(L):
L := false
– מנעול פנויL = false –
– מנעול תפוסL = true –
2002 מרץ
© אלן אזאגורי
23 עמוד
מימוש מנעולים
תמיכת חומרה compare&swap
compare&swap(mem, r1, r2)
– אם בזיכרון ) (memערך זהה לרגיסטר ,r1כתוב ערך r2
והחזר הצלחה
– אחרת החזר ערך כישלון
lock_acquire(L):
lock_release(L):
r1 = false
L := false
r2 = true
))while not compare&swap(L, r1, r2
do nop
ניתן לממש מונה אטומי
עמוד 24
אלן אזאגורי ©
מרץ 2002
מימוש מנעולים מודרני
load-linked & store conditional
ממומש ברוב הארכיטקטורות החדישות
– Compaq’s Alpha, IBM’s PowerPC, MIPS4000
צמד פקודות
– ) – LL(memקרא את ערך הזיכרון
– ) – SC(mem, valאם לא היתה כתיבה ל mem-מאז ה-
) LL(memהאחרון ,כתוב ערך valוהחזר הצלחה (אחרת
כשלון)
יותר כח מאשר לcompare&swap-
– ניתן לזהות כתיבות עוקבות של אותו ערך
עמוד 25
אלן אזאגורי ©
מרץ 2002
מימוש מנעולים
load-linked & store conditional
lock_acquire(L):
success = false
repeat
LL(L)
if not L then
success = SC(L, true)
until success
2002 מרץ
© אלן אזאגורי
lock_release(L):
L := false
26 עמוד
load-linked & store conditional
מתי חשוב לזהות כתיבות עוקבות של אותו
?ערך
הוצאת האיבר הראשון,– ברשימה מקושרת
remove_first(head):
element = NULL
A:if headNULL then
LL(head)
next_head = head->next
element = head
if not SC(head, next_head)
goto A;
return element
2002 מרץ
© אלן אזאגורי
27 עמוד