2011-02-08 7 views
5

Mam pytanie dotyczące wątków java.Synchronizacja wątku Java, najlepsze narzędzie współbieżne, operacja odczytu

Aby zrobić bardzo prosty przykład, powiedzmy, że mam 2 wątki.

Temat działającej instancji StockReader Klasa

Wątek B działającej instancji StockAvgDataCollector Class

nici B StockAvgDataCollector zbiera jakieś Giełdowe w sposób ciągły, czy jakiś ciężki uśredniania/manipulacji i aktualizuje zmienną składową spAvgData

W wątku A StockReader ma dostęp do instancji StockAvgDataCollector i jej członka spAvgData za pomocą metody getspAvgData().

Wątek A wykonuje operację tylko READ, a wątek B wykonuje operacje READ/WRITE.

Pytania

  1. Teraz muszę synchronizacji lub funkcjonalności atomową lub blokowania lub jakichkolwiek rzeczy związanych współbieżności w tym scenariuszu? Nie ma znaczenia, czy wątek A odczytuje starszą wartość.

  2. Ponieważ wątek A przechodzi tylko DO ODCZYTU i nie aktualizuje niczego, a tylko wątek B wykonuje dowolne operacje WRITE, czy będą jakieś scenariusze zakleszczenia?

Wkleiłem poniższy akapit z poniższego linku. Z tego akapitu wynika, że ​​muszę się martwić o blokowanie/synchronizację.

http://java.sun.com/developer/technicalArticles/J2SE/concurrency/

Reader/Writer Zamki

Podczas używania nici do odczytu danych z obiektu, nie ma konieczności, aby zapobiec inny wątek od czytania danych w tym samym czasie. Dopóki wątki czytają tylko i nie zmieniają danych, nie ma powodu, dla którego nie będą mogły czytać równolegle. Pakiet J2SE 5.0 java.util.concurrent.locks udostępnia klasy, które implementują ten typ blokowania. Interfejs ReadWriteLock utrzymuje parę powiązanych blokad, jeden do odczytu i jeden do pisania. Funkcja readLock() może być utrzymywana jednocześnie przez wiele wątków czytnika, o ile nie istnieją żadne programy piszące. Funkcja writeLock() jest wyjątkowa. Teoretycznie oczywistym jest, że użycie blokad czytnika/pisaka w celu zwiększenia współbieżności prowadzi do poprawy wydajności w porównaniu z blokadą wzajemnego wykluczenia. Jednak poprawa wydajności zostanie w pełni zrealizowana tylko na wielu procesorach i częstotliwości odczytu danych w porównaniu do ich modyfikacji, jak również czasu operacji odczytu i zapisu.

Które narzędzie współbieżne byłoby tańsze i odpowiednie w moim przykładzie?

java.util.concurrent.atomic?

java.util.concurrent.locks?

java.util.concurrent.ConcurrentLinkedQueue? - W takim przypadku obiekt StockAvgDataCollector zostanie dodany, a program StockReader zostanie usunięty. Żadna metoda getspAvgData() nie zostanie ujawniona.

Dzięki Amit

+0

Niestety nie wiedziałem. Po prostu zaakceptowałem wszystkie wcześniejsze pytania. Dziękuję za wskazanie. – FatherFigure

Odpowiedz

3

Cała lektura ReadWriteLock ma sens, jeśli masz wielu czytelników i przynajmniej jednego pisarza ... Gwarantujesz więc, że jesteś żywy (nie będziesz blokował wątków czytnika, jeśli nie pisze nic innego). Masz jednak tylko dwa wątki.

Jeśli nie masz nic przeciwko wątkowi B czytającemu stare (ale nie uszkodzone) wartości spAvgData, to wybrałbym AtomicDouble (lub AtomicReference, w zależności od tego, jaki typ danych spAvgData).

Więc kod wyglądałby następująco

public class A extends Thread { 
    // spAvgData 
    private final AtomicDouble spAvgData = new AtomicDouble(someDefaultValue); 

    public void run() { 
    while (compute) { 
    // do intensive work 
    // ... 
     // done with work, update spAvgData 
    spAvgData.set(resultOfComputation); 
    } 
    } 

    public double getSpAvgData() { 
    return spAvgData.get(); 
    } 
} 
// -------------- 

public class B { 
    public void someMethod() { 
    A a = new A(); 
    // after A being created, spAvgData contains a valid value (at least the default) 
    a.start(); 
    while(read) { 
     // loll around 
     a.getSpAvgData(); 
    } 
    } 
} 
+0

Dziękuję wszystkim za twoje odpowiedzi i myślę, że wszystkie z nich są dobre i zasługują na równą akceptację. Ale stackoverflow pozwala tylko jednej odpowiedzi zostać zaakceptowanym. – FatherFigure

2
  1. Jeśli nie przeszkadza nawlec może odczytać kompletny nonsens (w tym częściowo uaktualnionych danych), to nie, nie trzeba żadnej synchronizacji. Podejrzewam jednak, że powinnaś się zastanowić.
  2. Jeśli użyjesz pojedynczego muteksu lub ReentrantReadWriteLock i nie zawiesisz ani nie uśpisz bez limitu czasu podczas trzymania zamków, wtedy nie będzie żadnego zakleszczenia. Jeśli wykonasz niebezpieczne operacje na wątkach lub spróbujesz uruchomić własne rozwiązanie synchronizacji, musisz się o to martwić.

Jeśli używasz kolejki blokującej, będziesz potrzebować również stale uruchomionej pętli do przetwarzania w StockReader. ReadWriteLock jest nadal korzystny dla pojedynczego procesora lokalnego - problemy są takie same, niezależnie od tego, czy wątki są fizycznie uruchomione w tym samym czasie, czy tylko przeplatane przez przełączniki kontekstu.

Jeśli nie używasz przynajmniej jakiejś formy synchronizacji (np. volatile), Twój czytnik może nigdy nie widzieć żadnych zmian.

+0

Dzięki. Dobra informacja. – FatherFigure

3

Tak, synchronizacja jest ważna i należy wziąć pod uwagę dwa parametry: widoczności zmiennej spAvgData i atomowości jego aktualizacji. W celu zagwarantowania widoczności widoczności zmiennej spAvgData w wątku B przez wątek A, zmienna może zostać zadeklarowana jako volatile lub jako AtomicReference. Trzeba również pamiętać, że akcja aktualizacji to atomowa w przypadku, gdy w grę wchodzi więcej niezmienników lub akcja aktualizacji jest działaniem złożonym, z wykorzystaniem synchronizacji i blokowania. Jeśli tylko wątek B aktualizuje tę zmienną, to nie potrzebujesz synchronizacji, a widoczność powinna wystarczyć, aby wątek A odczytał najbardziej aktualną wartość zmiennej.

+0

Chociaż Java Spec gwarantuje, że aktualizacje do int (i mniejszych) i referencje są atomowe, więc niestabilne int lub odniesienie do obiektu zadziała, te ostatnie pod warunkiem, że obiekt został * zastąpiony * przez autora. –

+0

Dzięki. Dobra informacja. – FatherFigure

Powiązane problemy