Java: Mám neprázdný Set, ale nemůžu z něj dostat položky

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #60 kdy: 14. 04. 2018, 19:34:49 »
Ne, do kolekce se nedavaji Object. Davaji se tam jakykoliv tridy. U jakych kolekci je takhle nastavenej konktrakt (ja to vim)? Takze podle tvoji logiky nesmim menit zadny objekt, ktery je v kolekci? To by bylo asi hodne omezeny pouziti :)

Do kolekce se nedávají třídy, ale objekty splnující deklarované rozhraní.

Napsal jsem to spatne. Todle je lepsi definice


Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #61 kdy: 14. 04. 2018, 19:36:55 »
Jenom doplnění - k modifikacím Image nedochází přímo u prvků té kolekce, může k nim dojít jen v jiných instancích stejné entity jinde v kódu (tj. jiná proměnná, jiné místo v paměti, stejné UUID entity a stejný záznam v databázi). V kolekci pak zůstane neaktuální verze entity (u entit se používá eager loading). Neaktuální verze v kolekci ale ničemu nevadí, protože za chvíli bude aplikací použita a z kolekce odstraněna (tak funguje daná aplikační logika). Později se již do kolekce načte čerstvá verze. V tomto schématu by tedy podle mě mohlo dojít v nejhorším k tomu, že by v kolekci byla stejná entita 2x (pokud by se modifikací změnila identita, k čemuž ale v použitím frameworku nedojde). Takže synchronizovat tento druh modifikace není potřeba.

To je fakt tak těžké si obalit kolekci proxy vrstvou, která synchronizovaně zajistí všechny potřebné služby Image a nepřipustí přímou manipulaci s kolekcí?

Ne, ale proč to dělat? V daném případě to je úplně zbytečné. Taky se neptám, proč jedeš autobusem a ne vlakem, když „jet vlakem snad není tak těžké“. Jinými slovy, problém jsem opravil adekvátně k významu a rozsahu té aplikace a její funkčnosti. Tímto debatu končím a samozřejmě děkuju za příspěvky (jsem zvědavý na kolik stránek tu debatu ještě natáhnete, ale za mě to je uzavřené).

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #62 kdy: 14. 04. 2018, 19:37:25 »
Single thread si do toho zamotal ty.
Psal jsem o modifikacích prvků kolekce, které jste do toho zamotal mimo jiné vy. A psal jsem, že se to dělí na dvě varianty. Buď modifikace, které nemají vliv na hashCode() a equals() – takové modifikace kolekci vůbec nezajímají, takže není potřeba řešit žádnou synchronizaci. A nebo modifikace prvku, která má vliv na hashCode() a equals() – taková modifikace by byla pro hashovanou kolekci problém i v jednovláknovém prostředí, takže synchronizace by ničemu nepomohla.

Takze, kdyz nactu z ConcurrentHashMap prvek, zmenim ho a dam ho zpatky (se stejnym klicem), zajistil jsem viditelnost zmen v jinych trehaded nebo ne? Muzu zmenit ten prvek (ne klic)?
Když vložíte do ConcurrentHashMap jinou hodnotu pod původní klíč, bude pod tím klíčem nová hodnota viditelná ze všech vláken. Ale to je speciální vlastnost ConcurrentHashMap, která je speciálně pro konkurenční přístup určená. Pokud jenom změníte nějaké vlastnosti hodnoty, s mapou to vůbec nijak nesouvisí (a pro hodnoty v mapě nejsou důležité ani metody hashCode() a equals()) – pokud se tou hodnotou má pracovat ve více vláknech, musí ty změny být synchronizované. ConcurrentHashMap tomu nijak nepomůže.

Staraji. Kazdy volani zajistuje uplatneni happened-before.
Nestarají. Synchronizovaná jsou pouze volání metod na těch kolekcích. Co se děje s prvky kolekce ty kolekce vůbec nezajímá.

Například v tomhle kódu vám to druhé vlákno může vypsat 0, 1 nebo i hodnotu, kterou měla ta položka ještě dříve.
Kód: [Vybrat]
Item item = synchronizedMap.get("item1");
item.setValue(0);
new Thread(() -> item.setValue(1)).start();
new Thread(() -> System.out.println(item.getValue())).start();

Prave. Kdyz neco pridam do fronty, tak vsechny zmeny udelany predtim (i tech prvku), tak se uplatni.
Což je ale dané tím, jak fungují paměťové bariéry. Není to žádná specialita synchronizovaných kolekcí, protože úplně stejně se to bude chovat i při jakémkoli jiném použití synchronizačních primitiv.

Takhle to nevyznelo. Ale beru opravu.

Mně zase jako pravý opak vyznělo to vaše tvrzení:

Citace: Karel Rank
Jestli se modifikujou elementy kolekce, tak musi byt samozrejme synchronizovany pres stejny monitor.
Proto jsem na to reagoval.

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #63 kdy: 14. 04. 2018, 19:40:26 »
Ale špatná synchronizace přístupu při změně té fronty by neměla vést k trvalé nepoužitelnosti té fronty, ne? Takže jeden problém je, zda je synchronizace v pořádku a druhý problém je, jakto že se ta fronta dostane do nevalidního stavu (není prázdná ale nemůžu dostat její prvky a to ani při pozastavených vláknech jvm).

Tomu se rika race condition. Brian Goetz napsal skvelou knizku https://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601. Je ted ve sleve za $15. Stalo by zato si ji precist nez delat zavery, ze kdyz neco modifikuju pres nekolik threadu bez synchronizace, tak to nemuzu rozbit. Proto jsem psal, ze si hrajes na Doug Lea

Aha, dobře, díky za vysvětlení příspěvku. Problém nebyla absence synchronizace, ale špatná synchronizace (přes špatný objekt). Závěry jsem nedělal, ptal jsem se a odpověď jsem dostal již na cca druhé stránce této diskuze, totiž že se rozjede počítadlo se skutečným počtem prvků.

Na jiny masine to muze vypadat jinak. Proto je to race condition. A je jedno jestli to je absenci synchronizace nebo spatny synchronizaci.

Tímto je téma de fakto vyčerpáno, z literatury jsem si stáhnul Java Concurrency in Practice. Za mě už v debatě končím, klidně tu ale pokračujte  :)

Skvely! Doufam, ze stahnul = koupil  ;)

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #64 kdy: 14. 04. 2018, 19:41:43 »
Do kolekce se nedávají třídy, ale objekty splnující deklarované rozhraní.
Přičemž v JVM v kolekcích z Java Collections Framework je to deklarované rozhraní vždy java.lang.Object. Od Javy 5 výš dělá kompilátor „kouzla“ s generiky, takže ve zdrojovém kódu může být deklarované jiné rozhraní, ale v class file jsou metody kolekcí pořád deklarované jako booleanadd(Object item).


Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #65 kdy: 14. 04. 2018, 19:47:08 »
Do kolekce se nedávají třídy, ale objekty splnující deklarované rozhraní.
Přičemž v JVM v kolekcích z Java Collections Framework je to deklarované rozhraní vždy java.lang.Object. Od Javy 5 výš dělá kompilátor „kouzla“ s generiky, takže ve zdrojovém kódu může být deklarované jiné rozhraní, ale v class file jsou metody kolekcí pořád deklarované jako booleanadd(Object item).

Neni to pravda :) https://docs.oracle.com/javase/10/docs/api/java/util/Collection.html#add(E)

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #66 kdy: 14. 04. 2018, 19:53:58 »
Single thread si do toho zamotal ty.
Psal jsem o modifikacích prvků kolekce, které jste do toho zamotal mimo jiné vy. A psal jsem, že se to dělí na dvě varianty. Buď modifikace, které nemají vliv na hashCode() a equals() – takové modifikace kolekci vůbec nezajímají, takže není potřeba řešit žádnou synchronizaci. A nebo modifikace prvku, která má vliv na hashCode() a equals() – taková modifikace by byla pro hashovanou kolekci problém i v jednovláknovém prostředí, takže synchronizace by ničemu nepomohla.

Takze, kdyz nactu z ConcurrentHashMap prvek, zmenim ho a dam ho zpatky (se stejnym klicem), zajistil jsem viditelnost zmen v jinych trehaded nebo ne? Muzu zmenit ten prvek (ne klic)?
Když vložíte do ConcurrentHashMap jinou hodnotu pod původní klíč, bude pod tím klíčem nová hodnota viditelná ze všech vláken. Ale to je speciální vlastnost ConcurrentHashMap, která je speciálně pro konkurenční přístup určená. Pokud jenom změníte nějaké vlastnosti hodnoty, s mapou to vůbec nijak nesouvisí (a pro hodnoty v mapě nejsou důležité ani metody hashCode() a equals()) – pokud se tou hodnotou má pracovat ve více vláknech, musí ty změny být synchronizované. ConcurrentHashMap tomu nijak nepomůže.

Ne, to neni specialni vlastnost ConcurrentHashMap. To je vlastnost happens-before. Je to i u jinych kolekci, ktery jsou synchronized.

Staraji. Kazdy volani zajistuje uplatneni happened-before.
Nestarají. Synchronizovaná jsou pouze volání metod na těch kolekcích. Co se děje s prvky kolekce ty kolekce vůbec nezajímá.

Například v tomhle kódu vám to druhé vlákno může vypsat 0, 1 nebo i hodnotu, kterou měla ta položka ještě dříve.
Kód: [Vybrat]
Item item = synchronizedMap.get("item1");
item.setValue(0);
new Thread(() -> item.setValue(1)).start();
new Thread(() -> System.out.println(item.getValue())).start();

Jo, tendle kod je spatne.

Prave. Kdyz neco pridam do fronty, tak vsechny zmeny udelany predtim (i tech prvku), tak se uplatni.

Což je ale dané tím, jak fungují paměťové bariéry. Není to žádná specialita synchronizovaných kolekcí, protože úplně stejně se to bude chovat i při jakémkoli jiném použití synchronizačních primitiv.


Nahore si uvedl, ze to je specialiata ConcurrentHashMap. A ted ze to neni specialiata?

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #67 kdy: 14. 04. 2018, 20:11:42 »
Ne, to neni specialni vlastnost ConcurrentHashMap. To je vlastnost happens-before. Je to i u jinych kolekci, ktery jsou synchronized.
Takže je to speciální vlastnost ConcurrentHashMap jako synchronizované kolekce, jak jsem napsal.

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #68 kdy: 14. 04. 2018, 20:17:49 »
Ne, to neni specialni vlastnost ConcurrentHashMap. To je vlastnost happens-before. Je to i u jinych kolekci, ktery jsou synchronized.
Takže je to speciální vlastnost ConcurrentHashMap jako synchronizované kolekce, jak jsem napsal.

lol

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #69 kdy: 14. 04. 2018, 20:45:05 »
Do kolekce se nedávají třídy, ale objekty splnující deklarované rozhraní.
Přičemž v JVM v kolekcích z Java Collections Framework je to deklarované rozhraní vždy java.lang.Object. Od Javy 5 výš dělá kompilátor „kouzla“ s generiky, takže ve zdrojovém kódu může být deklarované jiné rozhraní, ale v class file jsou metody kolekcí pořád deklarované jako booleanadd(Object item).

Neni to pravda :) https://docs.oracle.com/javase/10/docs/api/java/util/Collection.html#add(E)

Proč se pouštíte do diskuse o něčem, čemu nerozumíte? Když napíšu, že v Java bytecode je to nějak a Java zdroják nad tím jenom dělá jakási cukrlátka, fakt není dobrý nápad napsat, že to není pravda a dokazovat to odkazem na JavaDoc, který popisuje právě ta cukrlátka v Java zdrojáku. Když se podíváte do bajtkódu, zjistíte, že tam je metoda opravdu definována jako java/util/Collection.add:(Ljava/lang/Object;)Z. A když si nastudujete něco o type erasure, pomocí kterého jsou implementovány generiky v Javě, pochopíte, proč je to tak v bajtcode. A pokud je bajtkód nad vaše síly, zkuste si to alespoň v Javě pomocí reflexe:
Kód: [Vybrat]
Method addMethod = java.util.Collection.class.getMethod("add", Object.class);Zkuste si tam místo Object.class dát jakoukoli jinou třídu, a uvidíte, zda takové metody existují…

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #70 kdy: 14. 04. 2018, 21:22:01 »
Do kolekce se nedávají třídy, ale objekty splnující deklarované rozhraní.
Přičemž v JVM v kolekcích z Java Collections Framework je to deklarované rozhraní vždy java.lang.Object. Od Javy 5 výš dělá kompilátor „kouzla“ s generiky, takže ve zdrojovém kódu může být deklarované jiné rozhraní, ale v class file jsou metody kolekcí pořád deklarované jako booleanadd(Object item).

Neni to pravda :) https://docs.oracle.com/javase/10/docs/api/java/util/Collection.html#add(E)

Proč se pouštíte do diskuse o něčem, čemu nerozumíte? Když napíšu, že v Java bytecode je to nějak a Java zdroják nad tím jenom dělá jakási cukrlátka, fakt není dobrý nápad napsat, že to není pravda a dokazovat to odkazem na JavaDoc, který popisuje právě ta cukrlátka v Java zdrojáku. Když se podíváte do bajtkódu, zjistíte, že tam je metoda opravdu definována jako java/util/Collection.add:(Ljava/lang/Object;)Z. A když si nastudujete něco o type erasure, pomocí kterého jsou implementovány generiky v Javě, pochopíte, proč je to tak v bajtcode. A pokud je bajtkód nad vaše síly, zkuste si to alespoň v Javě pomocí reflexe:
Kód: [Vybrat]
Method addMethod = java.util.Collection.class.getMethod("add", Object.class);Zkuste si tam místo Object.class dát jakoukoli jinou třídu, a uvidíte, zda takové metody existují…

Ne, neni takhle definovana v bytecode. Je definovana jako


  public abstract boolean add(E);
    descriptor: (Ljava/lang/Object;)Z
    flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
    Signature: #28                          // (TE;)Z


Dulezita je signature.


 TypeVariableSignature:
    T Identifier ;


Citace
Java zdroják nad tím jenom dělá jakási cukrlátka

Takze compiler bez zrojaku nevi jak ma nahradit generics? Jak ma delat strong type checking, protoze vsechno je Object? Ta informace neni v bytecode?

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #71 kdy: 14. 04. 2018, 21:54:29 »
Ne, neni takhle definovana v bytecode. Je definovana jako
Aha, budeme hrát najdete pět rozdílů. Nebo aspoň jeden:

(Ljava/lang/Object;)Z
(Ljava/lang/Object;)Z

Dulezita je signature.
Ne, není. To je jen doplňková informace pro kompilátor, JVM je to úplně ukradené.

Takze compiler bez zrojaku nevi jak ma nahradit generics? Jak ma delat strong type checking, protoze vsechno je Object? Ta informace neni v bytecode?
Pro nahrazování generik kompilátor ty rozšířené informace nepotřebuje, k tomu mu stačí raw typy. Aby mohl dělat strong type checking, jsou v class souboru doplněné ty typové informace navíc oproti bajtkódu, který zpracovává JVM. V raw typech nemusí být všechno objekt, je tam typ určený omezeními generik. Ty informace v class souboru jsou jako rozšířené atributy, které nepotřebuje JVM – podobně jako třeba ladicí informace (jména lokálních proměnných nebo čísla řádků).

A kolekce na tyhle rozšířené informace opravdu žádným způsobem nespoléhají. Ony kolekce byly součástí Javy už před Javou 5, a tehdy opravdu měly i ve zdrojáku jako parametr napsán typ Object. A protože rozhraní je stále zpětně kompatibilní, mají takový typ i dnešní raw kolekce.

Nechápu, proč si to nezjistíte sám, metodu Class.getMethods() snad znáte, takže všechny metody libovolného typu kolekce si můžete vypsat. Na třídě java.util.Collection těch metod add opravdu moc nenapočítáte, protože tam bude ta jedna jediná, která má jako parametr typ Object.

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #72 kdy: 14. 04. 2018, 22:29:54 »
Ne, neni takhle definovana v bytecode. Je definovana jako
Aha, budeme hrát najdete pět rozdílů. Nebo aspoň jeden:

(Ljava/lang/Object;)Z
(Ljava/lang/Object;)Z

Dulezita je signature.
Ne, není. To je jen doplňková informace pro kompilátor, JVM je to úplně ukradené.

Takze compiler bez zrojaku nevi jak ma nahradit generics? Jak ma delat strong type checking, protoze vsechno je Object? Ta informace neni v bytecode?
Pro nahrazování generik kompilátor ty rozšířené informace nepotřebuje, k tomu mu stačí raw typy. Aby mohl dělat strong type checking, jsou v class souboru doplněné ty typové informace navíc oproti bajtkódu, který zpracovává JVM. V raw typech nemusí být všechno objekt, je tam typ určený omezeními generik. Ty informace v class souboru jsou jako rozšířené atributy, které nepotřebuje JVM – podobně jako třeba ladicí informace (jména lokálních proměnných nebo čísla řádků).

A kolekce na tyhle rozšířené informace opravdu žádným způsobem nespoléhají. Ony kolekce byly součástí Javy už před Javou 5, a tehdy opravdu měly i ve zdrojáku jako parametr napsán typ Object. A protože rozhraní je stále zpětně kompatibilní, mají takový typ i dnešní raw kolekce.

Nechápu, proč si to nezjistíte sám, metodu Class.getMethods() snad znáte, takže všechny metody libovolného typu kolekce si můžete vypsat. Na třídě java.util.Collection těch metod add opravdu moc nenapočítáte, protože tam bude ta jedna jediná, která má jako parametr typ Object.

Samozrejme, ze kompilator ty rozsirene informace (jak tomu rikas) potrebuje pro generics erasure. Musi vedet, co ma nahradit, jestli to splnuje podminky (? extends F00b4r) etc... Takze to je soucasti definice metody v bytecode. To ze se nahrazujou unbounded typy Object na tom nic nemeni. Urcite vis proc to je zrovna Object.

Pokazdy, kdyz ti vyvratim tvoje tvrzeni, tak prijdes s necim jinym. Od bytecode definition (kde si dal neuplnou informaci), k tomu jestli JVM potrebuje singatures (o tom jsme se nebavili).

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #73 kdy: 14. 04. 2018, 22:53:37 »
Pokazdy, kdyz ti vyvratim tvoje tvrzeni, tak prijdes s necim jinym.
Tak ta moje pravdivá tvrzení nevyvracejte a já vám pak nebudu muset pomocí dalších tvrzení dokazovat, že jsou pravdivá.

jestli JVM potrebuje singatures (o tom jsme se nebavili).
Ne, o tom jsme se vůbec nebavili, akorát tím celá debata začala, když jsem vám vysvětloval, že kolekce nemůže použít vlastnosti žádného jiného typu, protože za běhu v JVM je v kolekci jenom typ Object.

Re:Java: Mám neprázdný Set, ale nemůžu z něj dostat položky
« Odpověď #74 kdy: 14. 04. 2018, 23:09:56 »
Pokazdy, kdyz ti vyvratim tvoje tvrzeni, tak prijdes s necim jinym.
Tak ta moje pravdivá tvrzení nevyvracejte a já vám pak nebudu muset pomocí dalších tvrzení dokazovat, že jsou pravdivá.

jestli JVM potrebuje singatures (o tom jsme se nebavili).
Ne, o tom jsme se vůbec nebavili, akorát tím celá debata začala, když jsem vám vysvětloval, že kolekce nemůže použít vlastnosti žádného jiného typu, protože za běhu v JVM je v kolekci jenom typ Object.

Napsal si na zacatku bs, pak ses ho snazil podporit polovicni pravdou a nakonec si hrajes na to, jak mentorujes. Pridavas irelevantni veci a zamotavas se do toho.