EDYCJA: Zakładam, że oznaczało to Queue<Object> objectList
zamiast ConcurrentLinkedQueue<Object> objectList
. ConcurrentLinkedQueue<Object>
robi już dla Ciebie całą gwarancję dotyczącą nici, co oznacza, że możesz dzwonić pod numer objectList.peek()
, nie tracąc z oczu warunków wyścigu. Jest to świetne, jeśli tworzysz programy wielowątkowe, ale nie jest to zbyt dobre dla nauki o bezpieczeństwie wątków.
Twoje metody nie muszą być synchronized
, zakładając, że masz jeden wątek działający na jednej instancji obiektu naraz, ale jednak jeśli potrzebujesz wielu instancji klasy, które wszystkie odnoszą się do tej samej zmiennej klasy statycznej, możesz trzeba synchronized
nad zmiennej klasy tak:
public static void getHeadObject() {
synchronized(safe.objectList) {
System.out.println(objectList.peek().toString());
}
}
to blokuje objectList
i nie pozwala na to, aby być odczytywane lub zapisywane w żadnym innym wątku, jak tylko program jest wewnątrz bloku synchronizacji. Zrób to samo dla wszystkich innych metod, aby uzyskać synchronized
.
UWAGA:
Jednakże, ponieważ robisz tylko jedną prostą operację get List.peek()
, naprawdę nie trzeba synchronizować nad objectList
ponieważ w wyścigu, będzie to uzyskać albo jedną wartość List
lub innym. Problem z warunkami wyścigu ma miejsce, gdy wykonywanych jest wiele złożonych operacji odczytu/zapisu, przy czym zmienia się między nimi wartość.
Na przykład, jeśli miał klasę PairInt
z PairInt.x
i PairInt.y
pól, z ograniczeniem, że x = 2y
i chciał zrobić
System.out.println(myIntPair.x.toString() + ", " + myIntPair.y.toString());
i inny wątek został aktualizujący wartość x
i y
w w tym samym czasie,
myIntPair.y = y + 3;
myIntPair.x = 2 * y;
I write wątek zmodyfikowany myIntPair
w przerwie między gwint odczytu na myIntPair.x.toString()
i myIntPair.y.toString()
możesz otrzymać dane wyjściowe, które wyglądają jak (10, 8)
, co oznacza, że działasz przy założeniu, że x == 2 * y
może spowodować awarię twojego programu.
W takim przypadku Twój odczytu musi użyć synchronized
, ale dla bardziej prostszych rzeczy jak peek()
na prostym object
które jest dodawane lub usuwane, niemodyfikowane podczas gdy w kolejce The synchronized
może, w większości przypadków zostać upuszczonym. W rzeczywistości, dla stanu string
, int
, bool
i tym podobnych, warunek synchronized
dla prostego odczytu powinien zostać usunięty.
Jednak zapisy powinny zawsze być synchronized
na operacjach, które nie są jawnie bezpieczne dla wątków, tj. Już obsługiwane przez java. I jak najszybciej zdobyć więcej niż jednego zasobu, lub wymagać, aby Twój zasób pozostają takie same w całej operacji, jak to zrobić wiele wierszy logiki do niego, wtedy musi używaćsynchronized
Dlaczego 'addObject' metodę instancji? Dlaczego nie statyczne? Dlaczego mimo to synchronizujesz wokół obiektu współbieżnego? Są już bezpieczne dla wątków. – Wug
Co masz na myśli przez Niekonsekwentny stan? –
Zakładam, że miał na myśli 'Kolejka