2010-06-19 14 views
10

Jeśli mam kilka właściwości zmienne w obiekcie, który będzie działać na kilka wątków, rozumiem, że powinny one być zsynchronizowane.Java. Jak poprawnie synchronizować pobierające i ustawiające?

class Doggie { 
    private String name; 
    private int age; 

    public void setName(String name) { this.name = name; } 
    public String getName() { return this.name; } 
    public void setAge(int age) { this.age = age; } 
    public int getAge() { return this.age; } 

} 

Pytania:

  • Czy nie return i przyporządkowanie operacje atomowe w Java?
  • Ponieważ właściwości niekoniecznie muszą być ze sobą powiązane, synchronizacja z tą samą blokadą nie zawsze ma sens. Jak zorganizować strukturę blokującą?
  • Czy lepiej jest zabrać ze sobą wewnętrzną blokadę lub prywatny wzór blokady obiektu?
+0

Co osiągnęłaby synchronizacja? Nawet jeśli można zagwarantować, że jeden wątek jest właścicielem funkcji setName(), gdy jest ona w tym miejscu, to po jej zakończeniu nic nie wskazuje na to, że inny wątek nie może natychmiast wykonać innego setName() przed pierwszym wywołaniem wątku getName(). Nigdy nie będziesz w 100% pewien stanu. –

Odpowiedz

10
  • Czy nie wrócić i przypisania operacje atomowe w Java?

Tak, są one atomowe (w niektórych przypadkach przynajmniej), ale atomowość nie jest jedyną kwestią.Inną ważną kwestią jest to, czy akcja zapisu do atrybutu przez jeden wątek jest widoczna dla następnego odczytu dla tego samego atrybutu utworzonego przez inny wątek.

  • Gdy czyta i pisze w tym samym wątku, odczyt jest gwarantowane, aby zobaczyć wcześniejszy zapis.

  • Gdy odczyty i zapisy są w różnych wątkach, odczyt jest gwarantowany tylko przy wcześniejszym zapisie, jeśli dwa wątki synchronizują się poprawnie ... lub jeśli atrybut jest zadeklarowany jako volatile.

Należy pamiętać, że prymitywne blokady/muteksy nie są jedynym sposobem synchronizacji.

  • Ponieważ właściwości nie może być koniecznie ze sobą powiązane, to nie zawsze ma sens, aby zsynchronizować z tym samym zamkiem. Jak zorganizować strukturę blokującą?

Sensowne jest używanie wielu zamków, jeśli (i tylko jeśli) spór o blokadę jest prawdopodobny. W tym przykładzie rywalizacja o blokadę może być problemem tylko wtedy, gdy pewna instancja Doggie otrzymuje bardzo wysoką liczbę operacji pobierania i/lub ustawiania.

  • Czy lepiej iść z wewnętrzną blokadą lub prywatnej wzór blokady obiektu?

To zależy. Jeśli twoja aplikacja korzysta z prymitywnej blokady obiektu Doggie, możesz uzyskać rywalizację o blokadę, a nawet niezamierzone zablokowanie operacji pobierania i ustawiania. W takim przypadku wskazany może być prywatny zamek. W przeciwnym razie blokada prywatna jest niepotrzebnym obciążeniem.

3

Operacje z odniesieniami są atomowe, ale nie są niestabilne - zawsze zobaczysz starą wartość lub nową wartość, ale nie ma gwarancji, że zobaczysz nową wartość bez jakiejś bariery pamięci. Nie pamiętam szczegółów, które prymitywy mają być atomowe - prawdopodobnie wszystkie, ale długie i podwójne.

Osobiście użyłbym pojedynczego prywatnego zamka, dopóki nie zobaczyłbym żadnych dowodów na jego wąskie gardło. Odradzam blokowanie "tego", ponieważ inny kod również może się na nim zablokować. Jeśli jesteś jedynym kodem, który zna blokadę, trudniej uzyskać interferencję. Powiedziawszy to, jeśli dzwoniący chcą atomowo zmienić więcej niż jedną nieruchomość, możesz odsłonić blokadę za pośrednictwem właściwości.

Czy na pewno potrzebujesz typu zmiennego z wątkami? Jeśli mógłbyś uniknąć tego wymogu, uprościłoby to życie.

1
  • Są to operacje atomowe, ale przedstawiają scenariusz, w którym dwaj klienci próbują uzyskać i ustawić dane w tym samym czasie. Nie ma gwarancji co do tego, które zamówienia będą wywoływane, co może mieć duży wpływ na wyniki twojego wniosku. (Klasycznym przykładem są transakcje pieniężne.)
  • Synchronizacja z tym samym zamkiem może być lub nie być sensowna - to naprawdę zależy od twojej aplikacji. Jednak zazwyczaj nie jest dobrym pomysłem zablokowanie całego obiektu, jeśli nie jest to konieczne.
  • Zgodnie z tym, co powiedział Jon, zacznij od pojedynczego, prywatnego zamka i idź tam, w zależności od wyników.
0

Masz rację, biorąc pod uwagę, że niezwiązane ze sobą właściwości mogą mieć różne blokady. Biorąc pod uwagę, że obiekty blokujące wymagają trywialnej pamięci, osobiście wybrałbym blokadę na właściwość zamiast jednej dla całego obiektu.

Lekki sposób to zrobić, aby mieć ustawioną wartość logiczną, podczas gdy właściwość jest zapisywana i czyścić w inny sposób. Największy sposób, aby to zrobić, aby obsługiwać limity czasu itp., Jest z muteksem.

+0

Muteksy Java nie obsługują limitów czasu. –

+0

Ach, to wstyd .. – Reinderien

+0

Cóż, "wbudowane" muteksy, które dostajesz z 'zsynchronizowanym' nie. Jeśli chcesz uzyskać timeouty, zawsze możesz jawnie użyć 'java.util.concurrent.locks.ReentrantLock', który ma metody' tryLock() 'z i bez limitów czasu. –

Powiązane problemy