2012-05-24 15 views
5

wpadłem na pewien (produkcja!) Kodu, który wygląda tak jak na poniższym fragmencie:Przypisywanie obiektu w zsynchronizowanym bloku opartego na tym obiekcie (Java)

synchronized(some_object) { 
    some_object = new some_object() 
} 

bym tego spodziewać podlegają wszelkiego rodzaju okropnych warunków wyścigowych i że drugi wątek może ewentualnie wejść do tego bloku, w którym tworzony jest nowy obiekt. Moje układy Java nie są wystarczająco dobre, aby stanowczo określić oczekiwane zachowanie powyższych, tak ciekawe, co ludzie mają do powiedzenia, zanim to zmienię.

Odpowiedz

2

Jak mówi Francis, nie może to stanowić problemu. Twój fragment jest odpowiednikiem tego:

SomeObject saved = some_object; 
synchronized(saved) { 
    some_object = new SomeObject() 
} 
+0

To nie jest tak napisane. W moim przypadku klasa ma zmienną some_object, która jest używana dla bloku synchronizacji, i ta zmienna jest ponownie przypisywana w tym samym bloku. –

+0

+1 Kluczem tutaj jest to, że synchronizacja odnosi się do obiektu, a nie do referencji. Po wykonaniu i przypisaniu 'new' nadal jesteś zablokowany na starym obiekcie. Nowy obiekt nie jest w tym momencie zablokowany. Po zsynchronizowaniu bloku blokada starego obiektu zostaje zwolniona i jeśli nie istnieją żadne inne odniesienia do niego, kwalifikuje się do gc. Jeśli w rzeczywistym zsynchronizowanym bloku jest więcej kodu i zależy to od tego, czy blokada w jakiś sposób przenosi się do nowego obiektu, może to być problem. –

+1

Dzięki Jim. Fakt, że zamek jest na obiekcie, a nie odniesienie, ma dla mnie sens. To, na czym się nie skupiałem, polegało na zmianie obiektu, do którego odnosi się ta zmienna, czy inny wątek zobaczy inny odblokowany obiekt i ponownie przejdzie do bloku, czy też mechanizmy zsynchronizowanego bloku zapobiegną temu? –

4

To może faktycznie być OK w zależności od tego, co się dzieje. Musisz zrozumieć większy kontekst. Synchronizacja nastąpi na obiekcie wskazywanym przez some_object na początku bloku. Z Twojego opisu jest za mało informacji, aby zobaczyć, że to błąd.

Synchronizacja sama w sobie zadziała.

1

Synchronizacja jest na obiekcie, który został odwołanie przy wejściu do bloku zsynchronizowanego. Wskazywanie odniesienia do innego obiektu wewnątrz bloku zsynchronizowanego w ogóle nie wpływa na synchronizację. Nadal jest zsynchronizowany z "starym" obiektem.

1

To bardzo źle. zsynchronizowane jest najlepiej używane na ostatnich członkach klasy.

Nowoczesne podejście do tworzenia obiektu w sposób bezpieczny dla wątków używa AtomicReference compareAndSet w pętli, jak omówiono w Goetz's Java Concurrency in Action (rozdział 15). Nie blokuje to twoich wątków i oferuje o wiele większą wydajność niż zsynchronizowany blok.

private final AtomicReference<SomeObject> someObject = new AtomicReference<>(); 


void buildIt() { 
    SomeObject obj = new SomeObject(); 
    SomeObject current = someObject.get(); //probably null, but doesn't matter 
    while (true) { 
     if (someObject.compareAndSet(current, obj)) 
      break; 
    } 
} 
Powiązane problemy