Zdeněk Troníček wrote:
To samozrejme platit musi - spravne receno, JIT si muze instrukce
prehazet jak chce, pokud to neovlivni beh programu. Specifikace nerika,
jak ma fungovat JIT. Rika jak mate jeho fungovani vnimat.
Ale nikde se tam nemluvi o tom, ze ten vysledek v pameti vidi  i ostatni
vlakna!
(http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.5)

Mam pocit, ze Ti nerozumim. Jak vlakno 2 ziska odkaz na objekt, ktery vytvari
vlakno 1? (Krome pripadu, kdy mu ten odkaz predame v konstruktoru objektu, coz
se vyslovne nedoporucuje). Preci pokud vlakno vytvari objekt pres new, tak
odkaz na objekt dostane az pote, co dojde k navratu z new. A to uz je objekt
inicializovan.
Jak jinak ho preda? Napr. ho precte bez synchronizace a volatility z nejakeho staticke fieldu. Kapitola 12.5 vazne nema vubec zadnou souvislost s casti speficikace o JMM. A to co je v ni napsano nelze v prostedi s vice vlakny nijak interpretovat.

Vlakno 2 proste nemusi videt zapisy do pameti ve vlakne 1 pokud:
a) vlakno 2 nevstoupi do synchronized sekci nad stejnym objektem, kterou pred vytvorenim objektu proslo vlakno 1.
b) vlakno 2 neprecte neco z volatile promene, do ktere zapsalo vlakno 1
c) pokud ma vlakno 2 spravny pointer na heap vidi spravne pouze final fieldy takoveho objektu (a vse referencovane pres ne dal - ale jen vytvorene a nastavene v kontruktoru*).

Takze pokud vlakno 2 dostane jinou cestou (pres normalni promenou) odkaz na objekt vytvoreny ve vlaknu 2 (napr. pres staticky field na nejake tride), tak i kdyz muze mit spravny pointer na heap, podle specifikace uvidi spravne jen obsah final promenych toho objektu. Nic vic. O nicem dalsim clanek dole nepise (pouze final fieldy nastavene v konstruktoru).

*) Tj. pokud mate final LinkedList a neco do nej pridate po opusteni konstruktoru tak to ostatni vlakna samozrejme nemusi videt.
Jinak tato vlastnost memory modelu se jmenuje Initialization safety a Google mi
o tom nasel napr. clanek http://www.ibm.com/developerworks/library/j-jtp03304/.

Bavime se o tomto?

class Complex { }
class Holder {
  final Complex C;
  Complex c;
  Holder() {
    C = c = new Complex();
  }
}

Pak objekt Complex bude plne inicializovan. Tj. vsechny finalni promenne budou
mit hodnotu, kterou jim nastavime inicializatorem nebo v konstruktoru. Muze se
ovsem stat, ze pro jine vlakno bude mit c hodnotu null, coz odpovida memu
prvnimu prikladu.

Pokud to ctete z holderu pres C, tak ono.
Neplati pro cteni pomoci holder.c; Tak muzete precist null, ale taky vnitrek typu Complex pri cteni pres c muzete videt spatne...

U te posledni vety ("Podobne kdyz pres getter..."), nevim co myslite.
Vlakno 1 vyrobi novy holder a ulozi ho dejme tomu do staticke volatile promenne. Vlakno 2 precte holder.C, a nasetuje ho do nejake staticke (nonvolatile) promenne odkud ho precte vlakno 3. Tak vlakno 3 nemusi videt vnitrek objektu typu Complex spravne. Protoze tato vlastnost je tranzitivni pouze pro pristup pres final promennou. Coz vlakno 3 porusi.

Odpovedet emailem