Zdeněk Troníček wrote:
Ahoj,
k situaci "PROBLEM" od verze 1.5 dojit nemuze. Drive to mozne bylo, ale od 1.5
ma Java "vylepseny" pametovy model a ten zarucuje, ze v okamziku, kdy new vrati
referenci, je objekt inicializovany (tj. probehl jeho konstruktor).
Todle prave v 1.5 neplati! Instrukce se porad muzou libovolne prehazet :-)
Instrukce se nemuzou prehazovat pres zapis do volatile nebo prechod pres
synchronizovanou sekci (tj. ostatni vlakna vidi, ze vsechno je provedeno
pred vstupem do synchronizovane sekce / zapisem do volatile).
V 1.4 a driv vyse uvedene neplatilo prave pro volatile. A neslo tedy
double-check-locking opravit nastavenim te promene na volatile.
Je vsak mozne neco jineho (mapa je sdilena promenna typu Map):
class Trida {
int x;
Trida(int x) {
this.x = x;
}
}
Vlakno 1:
Trida p = new Trida(42);
mapa.put("odpoved", p);
Vlakno 2:
Trida p = mapa.get("odpoved");
Pokud Vlakno 2 dostane referenci na objekt vytvoreny vlaknem 1, muze se stat, ze
v promenne x uvidi hodnotu 0 (defaultni hodnotu). Je to tim, ze program neni
spravne synchronizovan (mezi zapisem do x a ctenim x neni definovan
synchronizacni bod). Vlakno 1 totiz muze mit hodnotu 42 v cache a nemusi ji
okamzite zapsat do sdilene pameti (cache nemusi byt skutecna cache, ale treba
jen registr).
Je-li toto problem, lze to resit zavedenim synchronizacnich bodu nebo
jednoduseji pouzitim modifikatoru final ci volatile. Pokud by promenna x byla
final, bude jeji hodnota vzdy viditelna v ostatnich vlaknech.
Toto plati (pouze) pro final promene inicializovane v konstruktoru. A na
ty hodnoty musi to druhe vlakno pristupovat pres tu final promenou.
Pricemz tato vlastnost je tranzitivni.
Jinak misto Collections.synchronizedMap(...) je lepsi ConcurrentHashMap, ktera
povoluje soubezne cteni.
Z.T.