logo

Umpikuja Javassa

Javan lukkiutuminen on osa monisäikeistystä. Lukitus voi syntyä tilanteessa, jossa säie odottaa objektilukkoa, jonka toinen säike hankkii ja toinen säie odottaa objektilukkoa, jonka ensimmäinen säie hankkii. Koska molemmat säikeet odottavat toistensa vapauttavan lukon, tilaa kutsutaan umpikujaksi.

Umpikuja Javassa

Esimerkki lukkiutumisesta Javassa

TestDeadlockExample1.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(); } } 

Lähtö:

 Thread 1: locked resource 1 Thread 2: locked resource 2 

Monimutkaisempia lukkiutumia

Lukitus voi sisältää myös enemmän kuin kaksi säiettä. Syynä on, että umpikujan havaitseminen voi olla vaikeaa. Tässä on esimerkki, jossa neljä säiettä on lukkiutunut:

Lanka 1 lukitsee A, odottaa B:tä

Kierrä 2 lukkoa B, odottaa C

Kierrä 3 lukkoa C, odottaa D:tä

Kierrä 4 lukkoa D, odottaa A

Lanka 1 odottaa lankaa 2, lanka 2 odottaa lankaa 3, lanka 3 odottaa lankaa 4 ja lanka 4 odottaa lankaa 1.

Kuinka välttää umpikuja?

Ratkaisu ongelmaan löytyy sen juurilta. Umpikujassa se on resurssien A ja B käyttömalli, joka on pääkysymys. Ongelman ratkaisemiseksi meidän on yksinkertaisesti järjestettävä uudelleen lausekkeet, joissa koodi käyttää jaettuja resursseja.

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; } } } 

Lähtö:

 In block 1 In block 2 

Yllä olevassa koodissa luokka DeadlockSolved ratkaisee lukkiutuneen tilanteen. Se auttaa välttämään umpikujia ja ratkaisemaan ne, jos niitä tulee vastaan.

Kuinka välttää lukkiutumista Javassa?

Umpikujaa ei voida täysin ratkaista. Mutta voimme välttää ne noudattamalla alla mainittuja perussääntöjä:

    Vältä sisäkkäisiä lukkoja: Meidän on vältettävä lukitsemista useille säikeille, tämä on pääasiallinen syy lukkiutumiseen. Se tapahtuu yleensä, kun annat lukot useille säikeille.Vältä tarpeettomia lukkoja: Lukot tulee antaa tärkeille lankoille. Lukitseminen tarpeettomille lankoille, jotka aiheuttavat lukkiutumistilan.Ketjuliitoksen käyttäminen: Lukitus tapahtuu yleensä, kun yksi säie odottaa toisen päättymistä. Tässä tapauksessa voimme käyttää liittyä seuraan lanka kestää enimmäisajan.