סנכרון

userit8

New member
סנכרון

מישהו יכול להסביר לי מה הבעיה שהוא מדבר עליה?

The most common concurrency problem I've seen, is not realizing that a field written by one thread is not guaranteed to be seen by a different thread. A common application of this:

class MyThread extends Thread {
private boolean stop = false;

public void run() {
while(!stop) {
doSomeWork();
}
}

public void setStop() {
this.stop = true;
}
}
As long as stop is not volatile or setStop and run are not synchronized this is not guaranteed to work. This mistake is especially devilish as in 99.999% it won't matter in practice as the reader thread will eventually see the change - but we don't know how soon he saw it.
 

BravoMan

Active member
הבעיה היא כזו:

בזמן ש-run רץ ברקע ועושה את עבודתו, נים (thread) אחר שרוצה לעצור אותו אמור לקרוא ל-setStop.

על פניו, נראה שברגע שקראו לפונקציה stop הפונקציה run תעצר כי היא תראה ש-stop שווה true, אבל בפועל צריך מספר פעולות נפרדות כדי שזה יקרה, לכן לא ברור בכלל מתי הנים של run יראה את השינוי.

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

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

guaranteed to work

אני משתמש במבנה הזה כל הזמן. אין איתו שום בעייה, אם אתה לא מצפה ממנו למשהו מופרך.
 

selalerer

New member
במעבד המחשב יש זיכרון פנימי שנקרא אוגרים.

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

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

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

צריך לגלות ל-compiler (ולעוד רכיבים שהופכים את הקוד שלך לקוד מכונה במקרה של Java) ש-stop הוא משתנה שחולקים בו מספר threadים.

הדרכים לעשות את זה הן להגדיר את stop כ-volatile או לשים את הגישות אליו ב-synchronized block.
 

פרסאוס

New member


 
למעלה