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.
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
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). –