Deadlock-nie rozumiem czemu powsta?

2015-09-20 12:42

Rejestracja: 5 lat temu

Ostatnio: 1 rok temu

0

Wiem ze ten temat byl tutaj juz poruszany http://4programmers.net/Forum/Java/235550-deadlock_-_dlaczego Natomiast odpowiedz __krzysiek85 jest dla mnie nie zrozumiala. Wrzuce jeszcze raz kod tutaj

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() {
            public void run() { alphonse.bow(gaston); }
        }).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }).start();
    }
}

I teraz czemu tutaj niby te dwa watki sie wzajemnie blokuja mi sie wydawalo ze jezeli np. Alphonse zacznie sie wykonywac to zalozy blokade i do momentu az nie skonczy wykonywac bowBack tej blokady nie odda i dopiero wtedy Gaston bedzie mogl dzialac.Ale tak nie jest, w poscie do ktorego wrzucilem link __krzysiek85 pisze o dwoch monitorach do ktorych dostep musza uzyskac watki ale czemu, gdzie jest drugi?

Z gory dzieki za wszelkie odpowiedzi

Pozostało 580 znaków

2015-09-20 12:53

Rejestracja: 5 lat temu

Ostatnio: 1 rok temu

0

Chyba juz wiem to sie bierze stad : alphonse.bow(gaston) i gaston.bow(alphonse) i z tego ze w metodzie bow jest
bower.bowBack(this); czyli np dla alphonse.bow(gaston) bower==gaston a na ten obiekt moze byc juz zalozona blokada przez drugi watek. Dobrze mysle?

A tutaj jeszcze poprawiony przeze mnie kod, ktory zapobiega powstawaniu zakleszczenia

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");
        final Thread t = new Thread(new Runnable() {
            public void run() {
                alphonse.bow(gaston);
            }
        });
        t.start();
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                try {
                    t.join();
                    gaston.bow(alphonse);
                } catch (InterruptedException ex) {
                    System.out.println("Mam cie");
                }
            }
        });
        t2.start();
    }
}

Jesli ktos by mogl tez rzucic okiem czy to jest ok, to by bylo super:)

edytowany 1x, ostatnio: kdmrulez, 2015-09-20 13:06

Pozostało 580 znaków

2015-09-20 13:14

Rejestracja: 5 lat temu

Ostatnio: 2 lata temu

One nie tyle wzajemnie się blokują, co mogą wzajemnie się blokować (w tym przykładzie raczej tak się stanie). Dzieje się tak wtedy, gdy oba wątki są w metodach bow().
Na początku musisz wiedzieć, że jeśli używasz zapisu typu:

public synchronized void metoda() { 
    foo(); 
}

To jest to równoznaczne z zapisem:

public void metoda() {
    synchronized(this) {
        foo();
    }
}

Czyli lockiem jest domyślnie obiekt, w którym wywoływana jest metoda.

Teraz opiszę, jak powstaje deadlock:

  • Wątek 1 wchodzi do metody bow() obiektu alphonse i (jako że metoda jest synchronizowana) trzyma locka w postaci obiektu alphonse.
  • Wątek 2 wchodzi do metody bow() obiektu gaston i trzyma locka w postaci obiektu gaston.
  • Wątek 1 próbuje wywołać metodę bowBack() z obiektu gaston, więc musi być w posiadaniu locka (czyli obiektu gaston), ale nie może go dostać, bo trzyma go obecnie wątek 2, więc wątek 1 czeka.
  • Wątek 2 próbuje wywołać metodę bowBack() z obiektu alphonse, ale nie może, bo trzyma go wątek 1.
    Bum - oba wątki stoją.
edytowany 2x, ostatnio: Wizzie, 2015-09-20 13:18
Super wyjasnienie dzieki, to wlasnie mialem na mysli piszac swoj poprzedni post, ale Ty zrobiles to o wiele przejrzysciej. Wolalem sie upewnic, bo z tymi watkami nigdy nic nie wiadomo, niby program dziala teraz, ale nie ma pewnosci czy bedzie dzialal za jakis czas :) - kdmrulez 2015-09-20 14:23
A co do mojej poprawionej wersji, czy ona wyklucza powstawanie deadlock w tym przypadku? - kdmrulez 2015-09-20 14:23

Pozostało 580 znaków

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0