JavaRush /בלוג Java /Random-HE /מה זה מבוי סתום בג'אווה?
Alexey Smirnov
רָמָה
Москва

מה זה מבוי סתום בג'אווה?

פורסם בקבוצה
רמת הידע הנדרשת להבנת המאמר: סיימתם את המשימות Java Syntax ו-Java Core, וכעת אתם בתהליך של לימוד Java Multithreading. מבוי סתום או מבוי סתום ב-Java או מבוי סתום הוא שגיאה המתרחשת כאשר ל-threads יש תלות מחזורית בזוג אובייקטים מסונכרנים. תארו לעצמכם שפתיל אחד נכנס לצג האובייקט x, והשני נכנס למוניטור האובייקטים y. אם שרשור באובייקט xמנסה לקרוא לכל שיטה מסונכרנת באובייקט y, והאובייקט yמנסה באותו הזמן לקרוא לכל מתודה מסונכרנת באובייקט x, השרשורים יתקעו בהמתנה. מה זה מבוי סתום?  - 1להלן דוגמה מתוך המדריך של Java docs על מושג כזה כמו מבוי סתום. היכן מתרחשת כאן חסימת שרשורים?
public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        public synchronized void bow(Friend bower) {
            System.out.format("%s: %s" + "  has bowed to me!%n", this.name, bower.getName());
            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s"
                + " has bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new Runnable() {
            @Override
            public void run() {
               // System.out.println("Thread 1");
                alphonse.bow(gaston);
               // System.out.println("Th: gaston bowed to alphonse");
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
              //  System.out.println("Thread 2");
                gaston.bow(alphonse);
              //  System.out.println("2.gaston waiting alph bowed");
            }
        }).start();
    }
}
יש כאן שני דברים שחשוב להבין:
  1. מה בדיוק עושה כל אחד מהשרשורים הפועלים במקביל?
  2. באילו מנעולים משתמשים?
נתחיל מהסוף. נניח שיצרת שני אובייקטים של המחלקה Friend: alphonseו gaston. לכל אחד מהם יש מנעול משלו. לפיכך, ישנם שניים מהמנעולים הללו: ג'יגולו וגסטונים. כאשר נכנסים לשיטה מסונכרנת של אובייקט, הנעילה שלו ננעלת, וכאשר יוצאים מהשיטה, היא משתחררת (או נפתחת). עכשיו לגבי השרשורים. בואו נקרא לפתיל הראשון Alphonse(עם אות גדולה כדי להבדיל בינו לבין האובייקט אלפונס). הנה מה שהוא עושה (בואו נקרא לזה A, קיצור של Alphonse):
A: alphonse.bow(gaston) — получает лок alphonse;
A: gaston.bowBack(alphonse) — получает лок gaston;
A: возвращается из обоих методов, тем самым освобождая лок.
וזה מה שהשרשור עושה בזמן הזה Gaston:
G: gaston.bow(alphonse) — получает лок gaston;
G: alphonse.bowBack(gaston) — получает лок alphonse;
G: возвращается из обоих методов, тем самым освобождая лок.
עכשיו בואו נחבר את הנתונים האלה ונקבל את התשובה. ניתן לשזור חוטים (כלומר, האירועים שלהם יתרחשו) בסדרים שונים. מבוי סתום יעבוד, למשל, אם הסדר הוא כדלקמן:
A: alphonse.bow(gaston) — получает лок alphonse
G: gaston.bow(alphonse) — получает лок gaston
G: пытается вызвать alphonse.bowBack(gaston), но блокируется, ожидая лока alphonse
A: пытается вызвать gaston.bowBack(alphonse), но блокируется, ожидая лока gaston
מה זה מבוי סתום?  - 2
במקרה זה, שני החוטים חסומים וכל אחד מחכה שהשני ישחרר את המנעול. אבל אף אחד מהם לא יעשה זאת, כי לשם כך הם צריכים להשלים את השיטה שלהם, והיא נחסמת על ידי חוט אחר. אז הם היו תקועים איפה זה קרה deadlock. עם זאת, אפשר גם אריגה נוספת, שבה אחד החוטים יספיק להשלים לפני שהשני מתחיל:
A: alphonse.bow(gaston) — получает лок alphonse
A: gaston.bowBack(alphonse) — получает лок gaston
A: возвращается из обоих методов, открывая оба лока
G: gaston.bow(alphonse) — получает лок gaston
G: alphonse.bowBack(gaston) — получает лок alphonse
G: возвращается из обоих методов, открывая оба лока
במקרה זה, אין חסימה הדדית של חוטים. לדוגמה, נוספה שיטה כלשהי המאפשרת לשרשור אחר לקבל זמן לביצוע. כאשר התוצאה תלויה בסדר האירועים המתרחשים בו-זמנית (סדר מתוכנן או מהירות ביצוע), תהליך כזה נקרא מצב מירוץ ברוסית - "מצב מירוץ". לא כל תנאי המירוץ עלולים לגרום למבוי סתום, עם זאת, מניסיוני, רק תנאי המירוץ גורמים למבוי סתום. פורסם על ידי: דייב Lillethun
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION