Ahoj,

i) to Lukas M.:
Ten clanek (http://www.ibm.com/developerworks/library/j-dcl.html) znam, jenze - 
podobne jako vsechny ostatni, ktere jsem prosel - se zabyvaji singletonama. Z 
toho prameni moje nejistota, protoze to je prece jen trochu jiny pripad... v 
pripade singletonu nas zajima singleton jako takovy, v mem pripade nas zajimaji 
jine objekty, ktere dana mapa pouze agreguje.

ii) to Roman:
Zajimavy tip; po prostudovani javadocu to na me pusobi tak, ze pouziti 
ConcurrentHashMap bude mit i pozitivni vykonnostni dopady, protoze operace 
cteni jsou neblokujici a poskytuji vzdy posledni konzistentni vysledky zapisu. 
Koneckoncu i sam Doug Lea rika, ze ConcurrentHashMap byla zamyslena jako plna 
nahrada Hashtable. Nadruhou stranu jsem nikde nenasel, ze by to resilo uvedeny 
problem, coz ovsem neznamena, ze tomu tak neni - nemate nejaky "vysvetlujici" 
odkaz?

iii) to Lukas B.:
Tak to je prave to, cim si nejsem jisty. Mas pravdu, ze set/get jsou vzajemne 
synchronizovane, coz zaruci vzajemne blokovani cteni a zapisu. Dokonce mame i 
zaruceno, ze je kazdy Produkt vytvoren prave jednou. Ale je zaruceno to, ze se 
nekonzistentni produkt nedostane do jineho vlakna? Viz uvedeny priklad, kdy 
vlakno A ulozi nekonzistentni objekt do mapy a pak je preruseno. Podle me to 
zaruceno neni, protoze to by musely byt soucasne definovany prvky mapy jako 
volatile.
Jinak diky za zajimavy napad s dalsim urychlenim. V mem pripade to vsak nema 
vyznam, protoze produkty se incializuji jednou a pak se uz se jen ctou - a ta 
trocha blokovani na zacatku nas nezabije :-)


Diky vsem,
Jirka


>Ahoj,
>
>  uvedeny kod je spravne i pro viceprocesorove stroje.
>  Situace popsana v 1 nastat nemuze protoze kazdy zapis a cteni z 
>cacheOfProducts je synchronizovane (synchronizedMap) - tj. cteni zde po 
>zapisu vzdy pres synchronized. (put happens before get)
>  A pri vytvareni nove hodnoty synchronizuji vsechny vlanka pres 
>cacheOfProcuts, takze kazdy produkt je vytvoren prave jednou.
> 
>Pokud byste ten kod chtel jeste vice zrychlit (pokud soucasne prijde 
>vice vlaken s pozadavkem na ruzny produkt budou na sebe cekat na 
>cacheOfProducts), muzete zacit synchronizovat na nejakem wrapperu 
>Stringu vytvorenem stejnym zpusobem jako produkt (to ma smysl pouze 
>pokud new Produkt(name) muze byt hodne pomale - napr. cteni z DB). ;-)
>
>    Lukas
>
>
>Jiri Dolezel wrote:
>> Ahoj,
>> pracuji s JEE aplikaci provozovanou na viceprocesorovem stroji (Java 5), kde 
>> se casto pouzivaji konstrukce tohoto typu:
>>
>> **** zacatek prikladu ****
>>
>> class ProductsCache {
>>     // staticka cache: "nazev produktu" -> "DTO produktu"
>>     private static final Map<String,Product> cacheOfProducts 
>>             = Collections.synchronizedMap(new HashMap<String,Product>());
>>
>>     public Product get(String name) {
>>         // nejdrive jej zkusime najit v cache
>>         Product product = cacheOfProducts.get(name); 
>>
>>         if (product == null) {
>>             // pokud v cache neni, vytvor jej v synchronizovanem bloku
>>             synchronized (cacheOfProducts) {
>>                 // "double-checked-locking"?
>>                 product = cacheOfProducts.get(name);
>>
>>                 if (product == null) {
>>                     // PROBLEM: Muze se nam stat, ze se neuplne 
>> inicializovany produkt ulozi do cache 
>>                     // a jine vlakno tak ziska nekonzistentni produkt?
>>                     product = new Product(name);
>>                     cacheOfProducts.put(name, product);
>>                 }
>>
>>             }
>>         }
>>
>>         return product;
>>     }
>> }
>>
>> **** konec prikladu ****
>>
>> Mam k tomuto kodu dve otazky:
>> 1) Muze skutecne dojit k situaci popsane v kodu jako "PROBLEM"? Podle me 
>> ano, pokud prekladac/CPU prohodi instrukce takto:
>> - (vlakno A) vytvor novy objekt Produkt "nazev"
>> - (vlakno A) proved cacheOfProducts.put("nazev", product);
>> - (vlakno B) zavolej cacheOfProducts.get("nazev") => ziska nekonzistentni 
>> produkt
>> - (vlakno A) dokonci inicializaci produktu "nazev"
>>
>> 2) Pokud skutecne muze nastat situace 1), nabizi Java 5 moznost, jak tomu 
>> predejit, aniz bychom synchronizovali celou metodu get()? 
>>
>> Zkoumal jsem pouziti volatile za timto ucelem (tzn. deklarovat 
>> cacheOfProducts jako volatile), ale to se vylucuje s final. 
>> Ikdyby vsak cacheOfProducts nebylo final, resilo by volatile tento problem? 
>> Ve specifikaci se uvadi, ze prvky pole, ktere je deklarovane jako volatile, 
>> samy volatile nejsou. A jelikoz kolekce je postavena na polich, tak si 
>> myslim, ze to problem opet neresi. Ale to jsou jen me dohady.
>>
>> Prosim, pokud do toho vidite, vysvetlete mi cely problem jednou provzdy :-)
>>
>> Jirka
>>   

Odpovedet emailem