2009-11-26 19 views
8

Mamy dwa wątki uzyskujące dostęp do jednej listy za pomocą metody zsynchronizowanej. MożemyUpewnij się, że blokady synchronizowane Java są pobierane w kolejności?

a) polegać na uruchomieniu czas, aby upewnić się, że każdy z nich otrzyma dostęp do metody opartej na kolejności próbował lub

b) czy VM śledzić wszelkie inne zasady

c) Czy istnieje lepszy sposób na szeregowanie żądań?

Wielkie dzięki!

+1

Jest mało prawdopodobne, że naprawdę potrzebujesz tego wymagania. Może się okazać, że użycie ReentrantLock (true) jest znacznie wolniejsze niż wykonanie całej operacji zsynchronizowane. –

Odpowiedz

17

Nie, synchronizacja umożliwi dostęp w dowolnej kolejności (w zależności od implementacji maszyny JVM). Może to nawet spowodować, że wątki będą zagłodzić się w niektórych scenariuszach.

Możesz zapewnić zamówienie za pomocą ReentrantLock (od wersji Java 5.0) z opcją fair=true. (Lock lock = new ReentrantLock(true);)

+4

"zsynchronizowany da dostęp w kolejności losowej (lub kto najszybciej zdobędzie zamek)". Porządek nie jest po prostu określony. To prawie na pewno NIE jest losowe, i jest zależne od implementacji (i bardzo mało prawdopodobne), że "pierwszy" wątek zawsze otrzyma blokadę ... szczególnie w systemie wieloprocesorowym. –

+2

Masz rację, Stephen. Ale nie można przekazać na konkretnej implementacji, więc programista musi oczekiwać losowego zachowania. – Hardcoded

+1

Porządek nie jest losowy ani nie gwarantuje, że jest losowy. Gdy tylko jeden wątek blokuje, może być przełączany kontekstowo, więc nie będzie próbował ponownie przez jakiś czas, więc możesz uzyskać jeden wątek pośród wielu uzyskiwania blokady wiele razy, zanim inny wątek będzie miał szansę się obudzić. –

-1

Tak.

Jeśli dostęp do listy odbywa się za pomocą jednej zsynchronizowanej metody, współbieżne żądania z wielu wątków będą serializowane.

+2

@Conrad. Nie sądzę, że to prawda. Gdy wiele wątków czeka na monitor, można przyznać dowolne z nich w zależności od implementacji. Nie możemy być pewni, że monitor zostanie przyznany w kolejności, w której żądane są wątki. – Varun

+4

Odpowiadasz na subtelnie inne pytanie niż to, o co pytano. MrG pyta o porządek szeregowania kwestionowanych bloków synchronizowanych, a nie o to, czy bloki synchronizowane są przestrzegane. –

+0

Tak, choć myślę, że to nie ma znaczenia przez większość czasu. –

10

Nie można mieć pewności, że dwa połączenia z metodą zsynchronizowaną wystąpią w kolejności. Kolejność jest nieokreślona i zależy od implementacji.

Jest to zdefiniowane w sekcji JLS 17.1 Locks. Zauważ, że nic nie mówi o kolejności, w której wątki oczekujące na blokadę powinny uzyskać dostęp.

+0

Tak jak twoja odpowiedź, choć nic nie mówiąc, nie musi oznaczać, że nie będzie zamówienia, więc myślę, że będzie to zależało od implementacji. I myślę, że HotSpot/OpenJDK polegają na harmonogramie wątków systemu operacyjnego. – user454322

+0

@ user454322 - to uczciwa ocena. –

3

Nie można polegać na kolejności, w której określona metoda jest wywoływana z każdego wątku. Jeśli są to tylko dwa wątki, może być tak. Ale wyobraź sobie, jeśli istnieją 3 wątki i 1 wątek już uzyskany dostęp. Pozostałe 2 wątki, gdy spróbują uzyskać dostęp, będą czekać, a każdemu z nich można przyznać dostęp, a to nie zależy od kolejności, w której nazwała tę metodę. Nie zaleca się polegania na zamówieniu.

+3

"Więc nie sugeruje się polegać na zamówieniu." - To jest niedomówienie!! Powiedziałbym, że każdy program, który się na nim opiera, jest * zdecydowanie * nieprzenośny i * prawdopodobnie * buggy na platformie, na której został zaimplementowany/przetestowany! –

+0

@Stephen Nie można się zgodzić. – Varun

0

c) Czy istnieje lepszy sposób na szeregowanie żądań?

Czy przypadkiem używasz listy jako kolejki, tzn. Czy wzór użycia wygląda mniej więcej tak?

 
while (some condition) { 
    synchronized(theList){ 
     anItem = get and remove an element from theList 
    } 
    do some work with anItem 
} 

Jeśli tak, to może warto spojrzeć na interfejsie zamiast używania własnych schematów blokujące BlockingQueue. Implementacje (takie jak ArrayBlockingQueue) mają ustawienia dla uczciwości i więcej.

0

Zawsze zostawiam synchronizacje z serwerem aplikacji lub silnikiem, chyba że zdefiniuję własną intensywność.

Powiązane problemy