wielowątkowość - synchronizacja a wydajność

0

Witam,

piszę aplikację wielowątkową z użyciem synchronize.
Zależy mi na jak największej wydajności, powiedzmy, że każda milisekunda się liczy.
Aplikacja działa tak: napływają do mnie dane z różnych źródeł (udp itp.) ,
Dane przechowuje w klasie - wątku odpowiedzialnym za odbiór danych (wynik jako string) i powstała metoda, która pozwala na pobieranie i analogicznie ustawianie wartości.

 
public String getData() {
        synchronized (lockData) {
            return new String(data); //gdzieś wyczytałem, że utworzenie nowego obiektu pozwala na skrócenie locka?
        }
    }

Jest też wątek nadrzędny, który pobiera dane z tych wątków i zapisuje.
Wydajność nie jest jednak zadowalająca, pojawiają się kilku milisekundowe delaye. Jest możliwe takie zsynchronizowanie, żeby to wydajnie działało? Ktoś ma jakieś doświadczenia?

0

ile masz tych wątków?

0

Cztery dostarczają danych, jeden zapisuje, ale wydajność dosyć kiepska.

0
anonimowyalkoholik napisał(a):

Dane przechowuje w klasie - wątku odpowiedzialnym za odbiór danych (wynik jako string) i powstała metoda, która pozwala na pobieranie i analogicznie ustawianie wartości.

czego używasz do przechowywania tych danych? użyj StringBuffer, to samo co StringBuilder i jest od razu synchronizowany.

0

do kawałka kodu który podałeś wystarczy volatile.

0

jesli mogę, podłącze się do tematu
do czego służy typ volatile? gdzieś czytałem ze jest widoczny tak jakby.. w każdym wątku i jesli jeden go zmieni to każdy wątek widzi tę zmiane. Przynajmniej tak to zrozumiałem :) może mnie ktoś dokładniej uświadomić z jakimś przykładem? byłbym wdzieczny

0

W skrocie - pola ktore nie sa volatile moga byc przez JVM cachowane aby zwiekszyc wydajnosc i wtedy zapis z jednego watku moze (ale nie musi) nie byc od razu widoczny w innym watku. volatile oznacza 'tej, jvm nie cachuj mi tego pola, ono ma byc zawsze dostepne w swojej naswiezszej wersji dla kazdego kto je czyta'. Taki volatile ma rozne implikacje np. czytanie z niego powoduje flush innych watkow ktore do niego pisaly i takie tam.
Nie mam pojecia w czym volatile ma pomoc przy twoim problemie, ale co ja tam wiem.

0

w przypadku odczytania wartości i tylko ustawiania volatile jest wystarczające - zapis pojedynczej zmiennej (referencji też nawet jak jest 64 bitowa) jest operacją atomową. Jak powyżej napisał mućka - volatile powoduje że wątęk który czyta zawsze ma świeżą wartość z pamięci głównej, tak samo zapis od razu leci do pamięci głównej. Przy okazji pewnie leci więcej operacji między prockiem a pamięcią (read barier, write barier).
Problem pojawi sie w momencie jeżeli będą operacje skłądające się z kilku instrukcji np inkrementacja, wtedy synchronized.
Ewenutlanie można wykorzysatć Atomic*, które za pomocą CAS lepiej się "skalują" na wiele wątków.
Synchornized jest słówkiem które jest wydajne przy małym contentetion (nie wiem jak ładnie przetłumaczyć) - z powodu thin/fat locków. Jak więcej wątkół chcesz dostać się do sekscji krytycznej no to oczywiście wchodzi tylko jeden a reszta czeka (w wielkim uproszczeniu coś w rodzaju while(mam_wyłączoność()) )

Napisałeś o ile dobrze rozumiem że potrzebujesz tylko set/get. Kod który wkleiłeś to ewidentnie get. Jeżeli set też tylko ustawia wartość data, to za pomocą volatile masz kod nieblokujący i w efekcie copy-on-read.

można poczytać(choć może troche stary):
http://www.ibm.com/developerworks/library/j-jtp11234/

możę obczaj jak zachowuje się gc bo może to nie synchronizacja jest problemem- w sumie możesz mieć kilka ms na young albo full-gc na old jeżeli tych danych jest naprawdę dużo(kilkadziesiąt-kilkaset mb na pare skund ).

0

Spróbuj użyć kolejek np jakiejś implementacji BlockingQueue.

0

W tym kodzie nie da się stwierdzić jaki mechanizm synchronizacji jest potrzebny (i czy w ogóle jest potrzebny), bez wiedzy czym jest "data" i jak jest modyfikowany.
Jak ktoś twierdzi, że volatile wystarczy to chyba sobie wróży z fusów :P

0
moskitek napisał(a):

zapis od razu leci do pamięci głównej

Z tego co wiem niekoniecznie. Tam zachodzi relacja happens-before, czyli jedyne co jest zagwarantowane to to, ze zapisy do jakiejs referencji ktore sa 'wczesniej' w programie sa happen-before w stosunku do odczytow, czyli nowe wartosci sa przez odczyty widoczne. Nigdzie nie jest powiedziane ze zapisy musza byc natychmiastowe - podejrzewam ze jest to otwarte po to, aby mozliwe byly pewne optymalizacje - np. jeden watek zapisuje, a zaden nie czyta bo jakies ify costam odfiltrowaly - po co zapisywac do main memory skoro jest kosztowne i niepotrzebne?

0

Masz racje.

0

Dzięki za odpowiedzi, volatile jest nawet ok w moim przypadku, z pomiarów czasu wygląda na to, że działa to "troszeczkę" lepiej.
Ale takie jedno pytanko:

Może ktoś ma pomysł na strukturę programu (chciałbym porównać to co zrobiłem z Waszymi koncepcjami):
Muszę zsynchronizować dane pochodzące z różnych źródeł: udp,tcp, com, etc, tak żeby zapisywać je do csv z jedną datą, dane są odświeżane dość często (są to wielkości rzędu kilkudziesięciu milisekund).

0

a możesz powiedzieć coś więcej/dokładniej jakiś pseudokod - bo na razie sobie wróżymy z fusów. I gdzie masz ten delay - w tych 4 dostarczających czy ten zapisujący zamula (zapis pliku csv na dysk?)

1 użytkowników online, w tym zalogowanych: 0, gości: 1