מבוי סתום ב-Java הוא חלק מ-multithreading. מבוי סתום יכול להתרחש במצב שבו חוט ממתין לנעילת אובייקט, שנרכש על ידי חוט אחר וחוט שני ממתין לנעילת אובייקט שנרכש על ידי חוט ראשון. מכיוון ששני החוטים ממתינים זה לזה שישחרר את המנעול, המצב נקרא מבוי סתום.
דוגמה ל-Deadlock ב-Java
TestDeadlockExample1.java
עיצוב דפוסי java
public class TestDeadlockExample1 { public static void main(String[] args) { final String resource1 = 'ratan jaiswal'; final String resource2 = 'vimal jaiswal'; // t1 tries to lock resource1 then resource2 Thread t1 = new Thread() { public void run() { synchronized (resource1) { System.out.println('Thread 1: locked resource 1'); try { Thread.sleep(100);} catch (Exception e) {} synchronized (resource2) { System.out.println('Thread 1: locked resource 2'); } } } }; // t2 tries to lock resource2 then resource1 Thread t2 = new Thread() { public void run() { synchronized (resource2) { System.out.println('Thread 2: locked resource 2'); try { Thread.sleep(100);} catch (Exception e) {} synchronized (resource1) { System.out.println('Thread 2: locked resource 1'); } } } }; t1.start(); t2.start(); } }
תְפוּקָה:
Thread 1: locked resource 1 Thread 2: locked resource 2
מבוי סתום יותר מסובך
מבוי סתום עשוי לכלול גם יותר משני חוטים. הסיבה היא שיכול להיות קשה לזהות מבוי סתום. הנה דוגמה שבה ארבעה שרשורים נקלעו למבוי סתום:
חוט 1 נועל את A, ממתין ל-B
חוט 2 מנעולים B, מחכה ל-C
חוט 3 מנעולים C, מחכה ל-D
עיבוד מקביל
חוט 4 מנעולים D, מחכה ל-A
שרשור 1 מחכה לשרשור 2, שרשור 2 מחכה לשרשור 3, שרשור 3 מחכה לשרשור 4, ושרשור 4 מחכה לשרשור 1.
ג'אווה דייט עכשיו
איך למנוע מבוי סתום?
פתרון לבעיה נמצא בשורשיה. במבוי סתום זה דפוס הגישה למשאבים A ו-B, הוא הנושא העיקרי. כדי לפתור את הבעיה נצטרך פשוט לסדר מחדש את ההצהרות שבהן הקוד ניגש למשאבים משותפים.
DeadlockSolved.java
public class DeadlockSolved { public static void main(String ar[]) { DeadlockSolved test = new DeadlockSolved(); final resource1 a = test.new resource1(); final resource2 b = test.new resource2(); // Thread-1 Runnable b1 = new Runnable() { public void run() { synchronized (b) { try { /* Adding delay so that both threads can start trying to lock resources */ Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // Thread-1 have resource1 but need resource2 also synchronized (a) { System.out.println('In block 1'); } } } }; // Thread-2 Runnable b2 = new Runnable() { public void run() { synchronized (b) { // Thread-2 have resource2 but need resource1 also synchronized (a) { System.out.println('In block 2'); } } } }; new Thread(b1).start(); new Thread(b2).start(); } // resource1 private class resource1 { private int i = 10; public int getI() { return i; } public void setI(int i) { this.i = i; } } // resource2 private class resource2 { private int i = 20; public int getI() { return i; } public void setI(int i) { this.i = i; } } }
תְפוּקָה:
In block 1 In block 2
בקוד שלמעלה, Class DeadlockSolved פותר את המצב מסוג ה-deadlock. זה יעזור להימנע ממבוי סתום, ואם נתקלתם בפתרונם.
כיצד למנוע מבוי סתום בג'אווה?
לא ניתן לפתור לחלוטין מבוי סתום. אך אנו יכולים להימנע מהם על ידי ביצוע כללים בסיסיים המוזכרים להלן: