Synchronizowanie mutatorów i akcesorów

0

Cześć, mamy sobie prosty wraper na inta z getterem i setterem. O ile jasne dla mnie jest dlaczego getter musi być synchronizowany (widoczność) to w sumie co daje synchronizowanie settera?

Nie ma tam przecież żadnego check then act i żadnej innej compound action.

Jakie będą konsekwencje jak nie zsynchronizuję mutatora?

Czy to działa tak, że wtedy nadpiszę wartość z cache i akcesor mimo synchronizowaniu tego nie zobaczy?

2

Z tego samego powodu co getter, żeby zapewnić widoczność muszą być na tym samym mutexie, w Twoim przypadku na this.

Konsekwencje mogą być takie, że getter odczyta nie aktualną wartość

1

To ja dodam że w tym wypadku nie trzeba zakładać locka, można dać po prostu volatile na tego int'a i po kłopocie.

EDIT: To będzie dobrze działać bez locka tylko jak mamy ustawienie flag lub zapisanie wartości do odczytu (scenariusz jeden pisarz i wielu czytelników). Jeżeli ktoś będzie robił var += 1 to sam volatile nie wystarczy i trzeba lockować bo można zgubić zapis.

2
  1. Compare and swap :P
  2. AtomicInt / AtomicLong
2

W praktyce chyba nie ma różnicy między synchronizowaniem tu gettera i settera a volatile inta?

Gdy synchronizujemy jedno pole to różnica między synchronized, a volatile jest przede wszystkim wydajnościowa. Zwłaszcza po wywaleniu biased locking: https://openjdk.java.net/jeps/374

0

@0xmarcin:
No dobra, załóżmy, że mamy tego wrapera na inta, mamy getter i setter tak jak napisałem, nie ma żadnych złożonych akcji - po prostu odczyt i zapis. Robimy sobie tego inta jako volatile. Dlaczego nie może być wielu writerów?

Akurat var += 1 jest jasny bo to 3 operacje. Mówię o zwykłym setterze i getterze bez żadnych złożonych akcji.

0

Dlaczego nie może być wielu writerów?

Volatile nie gwarantuje że zapisy są atomowe. Gwarantuje jedynie że odczyt weźmie ostatnią zapisaną wartość i że odczyt wykona się po zakończeniu zapisu. Nie ma żadnej gwarancji ze dwa zapisy do tej samej zmiennej nie będą się przeplatać. Weź pod uwagę że zapis zmiennej nie musi byc operacją atomową na poziomie CPU. Twoje CPU ma pewnie 64 bity i na takich słowach umie operować. Jak masz zmienną 128 bitową, to jej zapis nie jest fizycznie możliwy do zrealizowania w 1 ticku!
Jeśli więc zapis takiej zmiennej wymaga 2 operacji, każda na 64 bitowym słowie, to nie masz gwarancji że 2 zapisy jednocześnie nie wygenerują ci niespójnego stanu, gdzie jedna połówka zmiennej została zapisana przez wątek X a druga przez wątek Y.

Przy okazji volatile zapewnia też atomowość odczytu, tzn jeśli odczytujesz zmienną której nie da się odczytać atomowo (np. tą naszą 128 bitową) to volatile zapewnia że w trakcie odczytu nikt nam jej w połowie nie zmieni.

https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html

2

@Shalom IMO zapędziłeś się.
volatile gwarantuje atomowość zapisów. Oczywiście problem będzie jeśli mamy odczyty powieszane z zapisami (jak w x = x + 1).

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