2015-08-05 11 views
5

Mam problem. Uważam, że ma to coś wspólnego ze współbieżnością lub synchronizacją wątków, choć nie mogę powiedzieć, co się dzieje.Współbieżność macierzy między połączeniami gniazdowymi

Oto mój opis przepływu danych dla naszego obiektu FriendRequestList.

Od strony klienta wysyłamy zaproszenie do innego użytkownika (pracownika). Wysyłamy więc prośbę i dodajemy naszą własną nazwę użytkownika do ich User.incFriendReq -list. Instancja to ArrayList tylko po to, aby uzyskać niezawodny odnośnik.

Przesyłamy teraz żądanie do serwera, aby otrzymać naszą własną listę zaproszeń (FriendRequestList.java).

Teraz problem. Jeśli użyję tego kodu poniżej, użytkownik nie zobaczy zaproszenia do znajomości, zanim zakończy swoje połączenie (wylogowanie), co spowoduje zamknięcie połączenia. Kiedy się zaloguje, zobaczy tylko prośbę na swojej liście.

kodu po stronie serwera:

... Worker.java ...

private Object getFriendRequests() { 
    User me = Data.getUser(myUserName); 
    if (me == null) { 
     return new NoSuchUserException(); // Don't worry about it ;) 
    } 

    return new FriendRequestList(me.getFriendReq()); 
} 

... User.java ...

private List<String> incFriendReq; 

public List<String> getFriendReq() { 
    return incFriendReq; 
} 

po stronie klienta

... Communicatio n.java ...

public FriendRequestList getRequests() { 
    sendObject(new GetRequests()); 
    return inputHandler.containsRequests(); 
} 

... MessageListener.java ...

public void run() { 
    ... 
    FriendRequestList requests = communication.getRequests(); 
    update(requestList, requests); 
    // Here we have the problem. requests.size is never different from 0 
} 

Jak zawsze, jeśli mogę zaktualizować Worker.java to zrobić w zamian:

private Object getFriendRequests() { 
    User me = Data.getUser(myUserName); 
    if (me == null) { 
     return new NoSuchUserException(); 
    } 
    return new FriendList(me.getFriends().stream().collect(Collectors.toList())); 
} 

Instant drugi użytkownik prosi o moją przyjaźń, widzę prośbę na mojej liście. Co daje? To brzmi dla mnie jak bazowa struktura danych nie jest aktualizowana, warunki wyścigu czy coś takiego. Ale poprawka polega na tym, że pobieram dane po stronie serwera, używając strumienia.

Proszę wyjaśnić, a także jak to zrobić w Javie 7, zanim strumienie rozwiążą mój, dla mnie, ciekawy problem.

Na marginesie

chcę dodać, że użytkownicy są umieszczone wewnątrz LinkedBlockingDeque i pobrać z obiektu Data, udostępnionym zasobem dla pracowników.

Odpowiedz

0

Wygląda na to, że zwrócenie listy incFriendReq bezpośrednio w getFriendReq jest jednym ze źródeł problemu. Kiedy używasz java 8 i przesyłasz tę listę do nowej listy, właśnie tworzysz kopię, więc nie ma żadnego użytecznego dodatku. W takim przypadku twój kod po stronie serwera powinien również działać, używając new ArrayList<>(me.getFriends()).

Sprawdziłbym, czy wszystkie wizyty na liście są poprawnie zsynchronizowane i czy wiesz, gdzie i kiedy lista jest mutowana.

+0

Fascynujące w tym kodzie jest to, że podczas debugowania lista, którą otrzymuję z 'getFriendReq' jest w rzeczywistości wielkości pierwszego. Ale kiedy otrzymam obiekt po drugiej stronie, ma on rozmiar zero. – miniwolf

+0

Wydaje mi się, że stan listy po stronie serwera nie jest prawidłowo utrzymywany. Lista może mieć rozmiar zerowy, ponieważ nieaktualna kopia listy wciąż była unoszona gdzieś do zwrócenia, ale nie była tą samą listą, co obserwowana wartość (sprawdź identyfikator obiektu w debugerze, aby zweryfikować) lub istnieje współbieżność problem związany z widocznością pamięci, która nie naraża zmutowanych danych na wątki (upewnij się, że wszystkie dostępy do listy są zsynchronizowane na tej samej blokadzie). –

Powiązane problemy