Keresés

Részletes keresés

el Papi Creative Commons License 2010.10.06 0 0 5439
private final Object mutex = new Object();

synchronized(mutex){
...
}

de hasznalhatsz vmilyen Lock implementaciot is ha Java5-tol felfele.
Előzmény: bigzed (5436)
angyalhentes Creative Commons License 2010.10.06 0 0 5438
De ahogy jobban megnézem, elvileg felemás értéket is visszaadhat, mert a második példából a h változó teljesen el is tűnhet az optimalizáció során. Vagy tévedek?

Előzmény: angyalhentes (5437)
angyalhentes Creative Commons License 2010.10.06 0 0 5437
Jaaa, én azt hittem, hogy valami felemás értékről van szó. :)

Nullát persze hogy visszaadhat.
Előzmény: el Papi (5435)
bigzed Creative Commons License 2010.10.06 0 0 5436
De mi az elegans/egyszeru megoldas akkor ha egy int (Integer) tipusu "dologra" szeretnek szinkronizalni?
Előzmény: bigzed (5427)
el Papi Creative Commons License 2010.10.06 0 0 5435
Beirom, mert tenyleg nem trivialis es nem is olyasmi amit az ember ki tudna bogaraszni anelkul hogy tovirol hegyire ismerne a JVM specifikaciot.

Szoval a kod a gyakorlatban szinte minden esetben a varhato visszateresi erteket adja, azonban olyan is elofordulhat hogy az elso ertek visszaadja a hash-t a masodik pedig 0-t!

A kovetkezo egy teljesen valid optimizacio egy JVM-tol:

int h = hash;
if (hash == 0) {
...
}
return h;
Előzmény: angyalhentes (5434)
angyalhentes Creative Commons License 2010.10.06 0 0 5434
Hát ezt most így fejből meg nem mondom (ha long lenne, akkor látom, hol a probléma), de leginkább arra céloztam, hogy ha egy objektumot több szálról is kell ráncigálni, akkor viszonylag egyszerű megoldani azt, hogy az történjen, amit akarsz.

Azt kibogarászni, hogy egy nem ilyesmire tervezett kód éppen miért hasal el, valóban nem triviális.
Előzmény: el Papi (5432)
el Papi Creative Commons License 2010.10.06 0 0 5433
Ez csak annyiban befolyasol, mintha mondjuk egy intern Stringre sycnhronizalnal, ha van meg a kornyeken megegy hasonloan "okos", akkor egyszercsak nem erti az illeto mitol van a live/deaklock.
Előzmény: crockl (5430)
el Papi Creative Commons License 2010.10.06 0 0 5432
Sajnos a multithreading tenyleg nem annyira egyertelmu neha, marcsak a nemdeterminisztikus viselkedes miatt.

Talalos kerdes:

ime a String osztay hashcode fv-e:

public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count;

for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}


Ezutan irjuk at a kovetkezokeppen:

public int hashCode() {
if (hash == 0) {
int off = offset;
char val[] = value;
int len = count;

int h = 0;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return hash;
}

Futtassunk ket threadet, amely parhuzamosan hivja ugyanannak a Stringnek a hashcode()-jat.
Mik a visszateresi ertekek?
Előzmény: angyalhentes (5429)
angyalhentes Creative Commons License 2010.10.06 0 0 5431
Az nem számít, mert ha nem változtatod az értéket, akkor ugyanaz a referencia marad. A new Integer() meg mindig új példányt ad vissza.
Előzmény: crockl (5430)
crockl Creative Commons License 2010.10.06 0 0 5430
ebbe a peldaba nem csak a ++ miatt szar, hanem mert 0-125-ig eleve az integer osztaly "cache" sub classabol kap 1 integer ojjektet :)
angyalhentes Creative Commons License 2010.10.06 0 0 5429
Nem akkora nagy varázslat ez, nem kell megijedni.

Egyszerűen csak a könyv szar.
Előzmény: bigzed (5427)
el Papi Creative Commons License 2010.10.06 0 0 5428
Ha szalkonkurenciaval foglalkozol akkor jeremy manson blogjat olvasd, o az egyik tarsszerzoje a java memory modelnek (Java5+), nala jobban kevesen ismerik.
Előzmény: bigzed (5427)
bigzed Creative Commons License 2010.10.06 0 0 5427
nagyon koszonom!
Igy mar ertheto minden!

Orom a megismeres!


(azert azt nem ertem miert akkora varazslat ez, hogy a JAVA 2. Utikalauz programozoknak c. konyvben ez hibasan szerepel ez a kod) :(
Előzmény: el Papi (5423)
el Papi Creative Commons License 2010.10.06 0 0 5426
A te konkrét esetedben az történt, hogy mindkét szál készített magának egy másolatot a static mezőről. Ezt megtehetik, mert nem tiltottad meg nekik a "volatile" kulcsszó használatával. Mindketten jól elvannak a maguk műsolataival, amivel hébe-hóba felülírják a változót.

Igen, errol kevesen tudnak: volatile nelkul nincs happens-before relacio biztositva thread interferencianal es nem garantalt az ertekek korrektsege.

Ez pl. egy olyan dolog, h az esetek 99,99%-ban nem fog hibat adni, csak majd vmikor amikor mar kinn van elesben a kod. Es emellett nehez elmagyarazni a legtobb fejlesztonek miert nem jo a kodja.
Előzmény: angyalhentes (5422)
bigzed Creative Commons License 2010.10.06 0 0 5425
huha, mig bepotyogtem a hozzaszolast jott meg szamos valasz. ugyhogy vissza az egesz, megprobalom megerteni a valaszokat. koszi
Előzmény: bigzed (5424)
bigzed Creative Commons License 2010.10.06 0 0 5424
Crockl, nem akarok visszaelni a turelmeddel, de probalkoznal meg beleverni az en fejembe is a tudast? Sajnos nem vilagos, amit irtal. ("Nem ugyan azt az integer object-et kapod")

(Integer class-t megneztem)

(egyebirant megjegyzem, hogy a kod az utikalauzbol lett kimasolva. meglepo szamomra, hogy ekkora "elvi" hiba van a konyvben)
Előzmény: crockl (5418)
el Papi Creative Commons License 2010.10.06 0 0 5423
az Integer egy immutable object.

az Integer osztaly peldanyai immutable objectek
Előzmény: el Papi (5420)
angyalhentes Creative Commons License 2010.10.06 0 0 5422
Hát ha szép egyenletes sorra számítottál, akkor olvasd el ezt:

http://java.sun.com/docs/books/jls/third_edition/html/memory.html

Nem tagadom, jó bonyolult, de érdemes megérteni.

A te konkrét esetedben az történt, hogy mindkét szál készített magának egy másolatot a static mezőről. Ezt megtehetik, mert nem tiltottad meg nekik a "volatile" kulcsszó használatával. Mindketten jól elvannak a maguk műsolataival, amivel hébe-hóba felülírják a változót.

A synchronized elvileg jó lenne vele, de megint tökönszúrtad magad az autoboxing-unboxinggal. A k++-ból ugyanis valójában ez lesz: k = new Integer( k.intValue()+1).

Így aztán minden szál minden egyes iterációban egy másik objektumra szinkronizál.

A legnagyobb tanulság alighanem az, hogy sose használj Integer-t, ha műveletet végzel vele, és ha ide-vel dolgozol, tiltsd le az autoboxingot, mert azt a keveset, amit nyersz vele, bőven elveszíted az ilyen szívásokkal.

Egy valamivel kisebb tanulság, hogy szinkronizálást így szoktak csinálni a paranoiás fejlesztők:

class X {
private final Object lock = new Object();
...
synchronized( lock ) {
...
}
...
}

Azért így, mert így semmilyen külső vagy belső tényező nem tudja megzavarni a szinkronizációt. Mivel private, külső osztály nem tud deadlockot okozni, és mivel final, nem esel bele abba a csapdába, amibe te most beleestél.
Előzmény: bigzed (5417)
el Papi Creative Commons License 2010.10.06 0 0 5421
O nem instance variable-on lockolt, hanem staticon, nem ezzel volt a gond, hanem hogy kihuzta a lockot a blokk alol.
Előzmény: kisspetya (5419)
el Papi Creative Commons License 2010.10.06 0 0 5420
Ahogy a multkor emlitettem, az Integer egy immutable object. Amikor ++Integer-t hasznalsz akkor egy masik Integer objectet kapsz vissza. Innentol pedig mar nem el a monitorlock.
Lock-olni final mezon erdemes(/kell). (en altalaban be is allitom a fordito erzekenyseget, hogy ha vki ilyet probalna le se forduljon).
Előzmény: bigzed (5417)
kisspetya Creative Commons License 2010.10.06 0 0 5419
Előzmény: bigzed (5417)
crockl Creative Commons License 2010.10.06 0 0 5418
lesd meg az Integer osztalyt. Nem ugyan azt az integer object-et kapod meg, igaz az ertek amit latsz az, egyforma, de megsem ugyan az az Integer objektum, ezert a lock az mukodik, csak epp nem ugy ahogy neked az kellene.

Lock-ra, ha valamiert ilyen kell, hasznalj sima Object-et
private Object lock = new Object();

es synchronized (lock ) {
Előzmény: bigzed (5417)
bigzed Creative Commons License 2010.10.06 0 0 5417
Sziasztok!

Bevallom, szep egyenletes sorra szamitottam, de ez lett belole. Tudna mondani v.ki v.mi okosat?
Koszonom.

public class SimpleCount1 extends Thread {
static Integer k = new Integer(1);

SimpleCount1(String name) {
super(name);
}

public void run() {
for (int i = 1; i <= 10; ++i) {
synchronized (k) {
System.out.println(getName() + ":"+k);
k++;
}
}
}

public static void main(String[] args) {
Thread thread1 = new SimpleCount1("th1"), thread2 = new SimpleCount1("th2");
thread1.start();
thread2.start();
}
}

kimenet:
th1:1
th1:2
th2:2
th1:3
th1:5
th1:6
th2:4
th1:7
th1:9
th2:8
th1:10
th2:11
th2:13
th2:14
th2:15
th2:16
th2:17
th2:18
th1:12
th1:20
el Papi Creative Commons License 2010.10.04 0 0 5416
De ha már, akkor arra is érdemes emlékezni, hogy a lokális változók által tárolt referenciák maguktól megszűnnek akkor, amikor a változo scope-jából kikerül a végrehajtás.

Ez annak a termeszetes kovetkezmenye h out of scope nem leteznek, tehat null ertekuek. Ez alapbol nem tul bonyolult de tobbszalu programok eseten mar konnyen adodhatnak felreertesek. A most hozzaadott closure-k eseten szinten adodhatnak bonyolultabb szituaciok.
Előzmény: angyalhentes (5415)
angyalhentes Creative Commons License 2010.10.04 0 0 5415
Abból indultam ki, hogy akinek új ez a referenciásdi, az nem indít helyből egy WeakHashMap-pel. :)

De ha már, akkor arra is érdemes emlékezni, hogy a lokális változók által tárolt referenciák maguktól megszűnnek akkor, amikor a változo scope-jából kikerül a végrehajtás.
Előzmény: el Papi (5413)
Rockmenyét Creative Commons License 2010.10.04 0 0 5414
Köszi mindenkinek, így azért már sokkal világosabb!!
Előzmény: angyalhentes (5411)
el Papi Creative Commons License 2010.10.04 0 0 5413
A *-os reszhez annyi kiegeszito, hogy ez a graf a strongreference eleire ervenyes. A soft, weak es phantom reference elek eseten mar nem vagy nem feltetlenul.
Előzmény: angyalhentes (5411)
NevemTeve Creative Commons License 2010.10.04 0 0 5412
.
angyalhentes Creative Commons License 2010.10.04 0 0 5411
A fontos tudnivaló, hogy itt minden más, mint a C++-ban.

Referencia nem törlődik magától. Vagy kézzel állítod null-ra, vagy úgy marad örökre.* Ha egy objektumra nincs több élő referencia, előbb-utóbb a gc magától összeszedi, tehát nem kell kézzel hívogatni. (Jobb helyeken le is van tiltva a kézi aktiválása, mert csak rontasz a helyzeten.)

A dispose() elvileg az ablakhoz kötődő natív erőforrásokat (buffereket, window handle-öket meg a franc tudja még mit) szabadítja fel ettől teljesen függetlenül. Feltételezem, hogy ezek az izék lazy inittel vannak megoldva, tehát dispose() után újrainicializálódnak, ha meghívod a megfelelő metódusokat.

A megoldás, hogy a dispose() meghívása után eldobsz minden, a frame-re mutató referenciát.

*Fontos tudni, hogy mi számít élő referenciának Javaban. A definíció szerint élő az a referencia, ami egy futó, vagy még el nem indult szálból kiindulva elérhető a referenciagráf irányított élein lépkedve. Ez azért jó, mert egyrészt nem kell aggódni a körkörös referencia miatt, másrészt meg nem kell egy objektum minden mezejét kinullázni, ha tudod, hogy magára az objektumra mutató referencia meg fog szűnni egyébként is.
Előzmény: Rockmenyét (5408)
el Papi Creative Commons License 2010.10.04 0 0 5410
En nem vagyok egy nagy GUI szakerto, de NevemTevenek igaza van. Amig van ervenyes (Strong)Reference egy object-re addig az per definicio nem kerulhet gc-re.
Nem vagyok tisztaban a JDesktop mukodesevel meg most nincs is idom hogy utana nezzek, de jo esellyel ha volt egy .add() hivas akkor nala is lesz egy ervenyes referencia az objektumhoz.
Azonkivul en a JInternalFrame javadocjaban nem latok semmi olyat ami miatt a dispose() hivasa utan neki null-nak kene lennie.
Előzmény: Rockmenyét (5408)

Ha kedveled azért, ha nem azért nyomj egy lájkot a Fórumért!