2012-04-19 23 views
6

Zgodnie z moim rozumowaniem poniższy fragment kodu powinien skutkować zakleszczeniem. Powód jest taki, że gdy wątek t1 blokuje statyczny obiekt firstData, uzyskał blokadę klasy. Tak więc, gdy próbuje zablokować kolejny statyczny obiekt secondData, żądanie powinno zostać zablokowane.Blokowanie statycznych elementów klasy

Jednak program działa poprawnie i drukuje *** Successfully acquired both the locks

co chodzi o blokowanie obiektów statycznych, że im brakuje tutaj?

public class Deadlock { 
    public static void main(String[] args) { 

     Thread t1 = new Thread(new DeadlockRunnable()); 
     t1.start(); 
    } 
} 

class DeadlockRunnable implements Runnable { 
    static Object firstData = new Object(); 
    static Object secondData = new Object(); 

    public void run() { 
     synchronized(firstData) { 
      synchronized(secondData) { 
       System.out.println("*** Successfully acquired both the locks"); 
      } 
     } 
    } 

} 

Dla wszystkich tych, którzy odpowiedzieli, że zamki są na obiekcie, zamiast klasy, proszę spojrzeć na this

Odpowiedz

14

Po pierwsze, masz błąd tutaj:

Powodem jest , gdy wątek t1 blokuje statyczny obiekt firstData, uzyskał blokadę klasy.

Blokowanie obiektu statycznego blokuje tylko ten obiekt, a nie klasę. Blokujesz dwa oddzielne obiekty.

The question you refered to jest o synchronized methods nie synchronized statements. Te dwa pokrewne konstrukty działają w nieco odmienny sposób.


Po drugie, nawet jeśli były blokowania na tym samym obiekcie, kod nadal nie impasu (ideone). Wewnętrzne blokady są reentrant. Oznacza to, że wątek nie blokuje samego zakleszczania się, jeśli próbuje dwukrotnie wykonać tę samą blokadę.

reentrant Synchronizacja

Przypomnijmy, że wątek nie może uzyskać blokadę posiadanych przez inny wątek. Ale wątek może uzyskać zamek, który już posiada. Umożliwienie wątku, aby uzyskać tę samą blokadę więcej niż raz, umożliwia ponowną synchronizację. Opisuje sytuację, w której zsynchronizowany kod, bezpośrednio lub pośrednio, wywołuje metodę, która zawiera również zsynchronizowany kod, a oba zestawy kodu używają tego samego zamka. Bez synchronizacji z synchronizacją zsynchronizowany kod musiałby podjąć wiele dodatkowych środków ostrożności, aby uniknąć zablokowania wątku.

Source

+1

Ponadto pojedynczy wątek nigdy nie spowoduje zakleszczenia. –

+0

Poniższy link w to uwierzył: http://stackoverflow.com/questions/437620/java-synchronized-methods-lock-on-object-or-class –

+0

Zgadzam się z @KirkWoll. Ale mam pytanie. Czy to oznacza, że ​​jeden wątek może jednocześnie blokować wiele obiektów statycznych? – noMAD

1

„gdy obiekt zamki wątek T1 statyczny FirstData, nabył zamek w klasie”
Nie wiem, dlaczego tak uważasz. t1 nabywa blokadę firstData, a nie klasy zawierającej. W twoim kodzie nie ma możliwego zakleszczenia.

EDIT
Po Twojego komentarza, link jest o różnicę między tymi deklaracjami 2:

public synchronized method() // lock on the instance (this) 
public static synchronized method() // lock on the class (Myclass.class) 

Ale nie ma związku z impasu.

+0

Poniższy link mnie uwierzył, więc http://stackoverflow.com/questions/437620/java-synchronized-methods-lock-on-object-lub-class –

+0

@assylias: Czy mógłbyś wyjaśnić, co obiekt zostanie zablokowany, gdy t1 przejmuje zablokować "firstData" (pole statyczne) ... Czy chodziło ci tylko o zablokowanie obiektu firstData? ... Ani klasy, ani kontenera DeadlockRunnable object? –

+0

@ tm.sauron Tak - blokada jest powiązana z określonym obiektem, w tym przypadku 'firstData' i' secondData' - klasa otaczająca 'DeadlockRunnable' nie odgrywa tutaj żadnej innej roli niż kontener kodu ... – assylias

Powiązane problemy