2013-02-18 13 views
17

Na przykład, czy to jest lepsze?Lepiej jest mieć zsynchronizowany blok wewnątrz bloku try lub blok try wewnątrz zsynchronizowanego bloku?

try { 
    synchronized (bean) { 
     // Write something    
    } 
} catch (InterruptedException e) { 
    // Write something 
} 

Albo tak jest lepiej:

synchronized (bean) { 
    try {   
     // Write something    
    } 
    catch (InterruptedException e) { 
     // Write something 
    } 
} 

zastanawiałem się, która z nich jest najlepsza praktyka. Oczywiście biorąc pod uwagę muszę zsynchronizować cały kod wewnątrz bloku try. Nie mówię o przypadku, że muszę zsynchronizować tylko część kodu wewnątrz try (w tym przypadku myślę, że byłoby lepiej mieć blok synchronizujący wewnątrz try). Moje wątpliwości dotyczą przypadku, w którym muszę zsynchronizować cały blok try.

Odpowiedz

11

Lepiej jest mieć zsynchronizowany blok wewnątrz bloku try lub blok try wewnątrz zsynchronizowanego bloku?

Chyba że wyraźnie potrzebują catch się w bloku synchronized, chciałbym zrobić sekcję synchronized kodu tak małe, jak to możliwe i to wewnątrz try/catch. Tak więc pierwszy wzór byłby lepszy. Następnie, jeśli musisz wykonać operacje w sekcji catch (jak logować wyjątek lub ponownie przerwać wątek, patrz poniżej), nie zablokują one innych wątków.

Powiedział, że jeśli blok synchronized zawiera liczbę linii (zwykle nie jest dobrym pomysłem oczywiście) to chciałbym rozważyć przeniesienie bloku try/catch bliżej do metody, która zgłasza wyjątek (prolly wait lub notify). Przy dużej liczbie linii istnieje ryzyko nieprawidłowej obsługi wyjątków za pomocą dużych bloków try/catch. Zależy trochę od układu odniesienia tutaj.

Jak na bok, upewnij się, że co najmniej dziennika przerwane wyjątki. Nigdy nie ignoruj ​​ich. Prawdopodobnie chcesz ponownie przerwać wątek:

try { 
    ... 
} catch (InterruptedException e) { 
    // always a good pattern 
    Thread.currentThread().interrupt(); 
    // handle the interrupt here by logging or returning or ... 
} 
+0

'Jeśli więc musisz wykonać operacje w sekcji catch ... nie zablokuje to innych wątków." Dlaczego zrezygnujemy z blokady z powodu wyjątku? – Cratylus

+0

Jak powiedział @Gray, musisz wybrać nagranie do pożądanego efektu, zsynchronizować akcję bloku catch i nie, i mieć najmniejszy zsynchronizowany blok, jak to możliwe. Ale myślę, że musisz wziąć pod uwagę blok try-catch otaczający kod, który naprawdę chcesz ochronić, unikając większych bloków, co oznacza, że ​​możemy podsumować te dwie dobre praktyki programistyczne: 1. Zachowaj małe zsynchronizowane bloki 2. Zachowaj try/catch bloków otaczających kod, który naprawdę chcesz strzec. –

+0

"Dlaczego mielibyśmy zrezygnować z blokady z powodu wyjątku". Ponieważ połączenia dzienników mogą być synchroniczne i kosztowne? Zależy to od kodu znajdującego się w bloku 'catch' bloku @Catatylus. – Gray

0

Czy ma znaczenie, czy twój blok catch jest zsynchronizowany? Ponieważ masz "napisać coś", zakładam, że będziesz robił jakieś logowanie, które nie musi być zsynchronizowane z dobrym szkieletem logowania, co oznaczałoby, że odpowiedź jest prawdopodobnie nie.

Generalnie, twoim celem powinno być jak najmniejszej synchronizacji. Im mniejsza blokada synchronizacji, tym mniejsze prawdopodobieństwo wystąpienia problemów.

3

Nie ma najlepszej praktyki. Zależy tylko od tego, czy potrzebujesz części obsługi wyjątku wewnątrz zsynchronizowanego bloku, czy nie. Możesz chcieć jednego lub drugiego i wybrać taki, który sprawia, że ​​zsynchronizowany blok jest najkrótszy, jednocześnie czyniąc kod poprawnym i bezpiecznym dla wątków.

0

W tym przypadku może się zdarzyć InterruptedException tylko wewnątrz bloku synchronized gdzie można też nazwać wait lub sleep lub notify.

Ogólnie najlepszą praktyką jest umieszczenie bloku try/catch tak blisko kodu, który może wyrzucić wyjątek, aby ułatwić identyfikację kodu, który należy naprawić.

0

Nie ma to nic wspólnego z synchronized{try{}} lub try{synchronized{}}, ale wszystko ma związek z synchronized{catch{}} lub synchronized{} catch{}.To naprawdę zależy od tego, co robisz w bloku catch.

Jednak biorąc pod uwagę, dla InterruptedException, zazwyczaj powinieneś zrobić catch{} poza synchronized{}.

2

Wydaje się, że to tylko estetyczne pytanie. Nie jest. Jest to pytanie funkcjonalne, a odpowiedź jest podyktowana wymogiem w każdym indywidualnym przypadku. Każdy zsynchronizowany blok powinien być tak duży, jak to konieczne, aby zawierał wszystko, co musi być zsynchronizowane, i nie większy.