Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
VODA

Založen: 29. 07. 2007 Příspěvky: 1721 Bydliště: Plzeň
|
Zaslal: 26. prosinec 2011, 19:58:22 Předmět: Synchronizace :: dereference |
|
|
Zdravím,
hraji si tu s mou semestrálkou na sítě a narazil jsem na něco, u čeho si nejsem vůbec jistý, zda se tím zabývat.
Jde mi zkrátka o to, že všem vláknům hráčů předám ukazatel na game manager, jeho metody obsahují nějakou synchronizaci (mutexem)...
Když nějakou zavolám, třeba takto: obj->fn(); tak je to stejné jako kdybych napsal (*obj).fn(); ... používá se tedy dereference...
No a mě zajímá, co se děje, když dochází k dereferenci...konkrétně v případě, že budu toto volat z více vláken...nemůže tam dojít k nějakému nesynchronizovanému přístupu nebo tak něco?
Díky. S vlákny si hraji chvilku, takže si nejsem vůbec jistý... _________________ Opravdovost se pojí s trýzní... |
|
Návrat nahoru |
|
 |
Tringi

Založen: 28. 07. 2007 Příspěvky: 290
|
Zaslal: 26. prosinec 2011, 20:24:53 Předmět: |
|
|
Pakliže ten obj pointer předáváš, zůstává stejný, tak se ničeho obávat nemusíš.
Normálně kompilátor zná adresu objektu a přímo s ní pracuje, tady si ji jen musí nejprve přečíst z proměnné, nic na co bys musel být zvlášť opatrný.
Funkce fn pak samozřejmě musí, v nejjednodušším případě být kanonicky uzavřena v mutexu (nebo kritické sekci), nebo lépe (je-li těch vláken hodně) synchronizovat přístup ke sdíleným datům. _________________ WWW | GitHub | TW |
|
Návrat nahoru |
|
 |
Quiark

Založen: 29. 07. 2007 Příspěvky: 816 Bydliště: Chlívek 401
|
Zaslal: 27. prosinec 2011, 00:45:08 Předmět: |
|
|
Synchronizovaný přístup do paměti je potřeba jen když do ní ve kterémkoliv vlákně zapisuješ (a u lock-free ani to ne . Při dereferenci se čte, nic se nezapisuje, takže není problém.
EDIT: upřesnění _________________ Mám strach
Naposledy upravil Quiark dne 27. prosinec 2011, 09:28:35, celkově upraveno 1 krát |
|
Návrat nahoru |
|
 |
Marek

Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 27. prosinec 2011, 03:38:05 Předmět: |
|
|
To není tak úplně přesné. I čtení je třeba chránit zámkem v některých případech, viz níže.
Pokud je proměnná read-only, přístup k ní nepotřebuje žádné zámky. Read-only proměnná je i taková, která se nastaví jednou při inicializaci a během běhu více vláken se už nemění.
Pokud se proměnná může měnit během běhu více vláken, jakýkoliv přístup k ní musí být chráněný zámkem a to i když se z ní jen čte. Ten zámek je svázaný s tou proměnnou a měl by pouze chránit přístupy k té proměnné. Samozřejmě větší kus kódu, který nad tou proměnnou pracuje, by měl být celý chráněný zámkem po celou dobu jeho běhu.
Místo zámků se dají použít i atomické operace, ale jen někdy. Některé operace jsou atomické defautně, ale toho se taky dá využít jen někdy.
Některé datové struktury fungují bez zámků, ale tam jsou využívány triky, jak toho dosáhnout. Typický příklad je ring buffer, kde jedno vlákno pouze čte a druhé pouze zapisuje. _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
 |
Tringi

Založen: 28. 07. 2007 Příspěvky: 290
|
Zaslal: 27. prosinec 2011, 04:26:51 Předmět: |
|
|
...což je dost komplikovaná problematika, kde i programátoři s roky zkušeností snadno udělají heisenbug (chyby, které se projeví zřídka a náhodně). Guilty as charged
Navíc dnes, na moderních OS, v 99% ani korektní lock-free synchronizací nic nezískáš. Jelikož se zabývám především vývojem nad Windows, tak můžu jako příklad uvést kritické sekce: Ty byly v každé major verzi totálně překopány a stávající verze (Vista a novější) v ideálním případě (žádné jiné vlákno není uvnitř dané kritické sekce) trvá jen pár instrukcí, provede se de facto atomická operace, bez context-switche, bez přepnutí do kernel módu. Věřím že podobně vyladěné to za ty roky mají všechny OS dnes. _________________ WWW | GitHub | TW |
|
Návrat nahoru |
|
 |
Marek

Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 27. prosinec 2011, 06:57:53 Předmět: |
|
|
Podle mě to není moc komplikované, ale běžně se setkávám s lidmi, kteří programují kód pro multivláknové prostředí jako by tam bylo jen jedno vlákno, a tváří se, jako by všechno bylo v pořádku.
Akorát jsi nevysvětlil, proč v 99% případů lock-free kódem nic nezískáš. Jenom jsi to zmínil a pak jsi se začal bavit o implementaci Windows. Myslel jsi to tak, že mutex interně využívající atomické operace není o moc horší než použití atomické operace přímo (což se běžně používá pro implementaci lock-free kódu)?
Zásadní rozdíl bych viděl v tom, že když dojde ke kolizi dvou vláken při vstupu do mutexu, tak jedno vlákno se uspí a tedy dojde ke context switchi. Pokud se stejná kolize stane u atomické instrukce, tak ke context switchi dojít nemusí, jenom se vykonávání vlákna pozastaví hardwarem na dobu nezbytně nutnou. Další věc je, že vstup do mutexu má nějakou režii (volá se tam na to nějaká funkce a operuje se tam s nějakou pomocnou strukturou), zatímco atomická operace přímo odpovídá instrukci v asm. (možná jen na Windows je ještě obalena ve WinAPI funkci) _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
 |
rezna
Založen: 27. 07. 2007 Příspěvky: 2156
|
Zaslal: 27. prosinec 2011, 09:04:28 Předmět: |
|
|
Marek napsal: |
zatímco atomická operace přímo odpovídá instrukci v asm. (možná jen na Windows je ještě obalena ve WinAPI funkci) |
InterlockedIncrement apod. |
|
Návrat nahoru |
|
 |
VODA

Založen: 29. 07. 2007 Příspěvky: 1721 Bydliště: Plzeň
|
Zaslal: 27. prosinec 2011, 09:48:35 Předmět: |
|
|
Oki, takže tu dereferenci řešit nemusím? Předpokládám, že když je na levé straně [ obj->fn(); ], tak nedochází ke čtení ani zápisu do sdílené paměti, tudíž není třeba synchronizovat, jo? _________________ Opravdovost se pojí s trýzní... |
|
Návrat nahoru |
|
 |
rezna
Založen: 27. 07. 2007 Příspěvky: 2156
|
Zaslal: 27. prosinec 2011, 10:56:53 Předmět: |
|
|
samozrejme ze dochazi ke cteni ze sdilene pameti - nicmene je to misto, ze ktereho se pouze cte -> neni treba resit synchronizaci
mam ale obecne pocit ze moc nevis na co a jak se synchronizace pouziva -> bylo by dobre trochu vice neco nacist ... |
|
Návrat nahoru |
|
 |
Marek

Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 27. prosinec 2011, 11:07:38 Předmět: |
|
|
rezna> Jo, to jsem myslel.
VODA> To nejde tak přímo určit z jednoho fragmentu kódu. Volání funkce samo o sobě problematické není, ale uvnitř fn už to může být úplně jinak. Samozřejmě dochází minimálně ke čtení (sdílené) paměti. Všechna paměť procesu je vždy sdílená mezi vlákny toho procesu. (teď si nejsem jistý, jak je to se zásobníkem) EDIT: rezna byl rychlejší  _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
 |
VODA

Založen: 29. 07. 2007 Příspěvky: 1721 Bydliště: Plzeň
|
Zaslal: 27. prosinec 2011, 11:47:03 Předmět: |
|
|
Oki, mě konkrétně zajímalo volání funkce samotné. Nic jiného. Jen mě tam mate ta dereference... _________________ Opravdovost se pojí s trýzní... |
|
Návrat nahoru |
|
 |
OndraSej

Založen: 28. 07. 2007 Příspěvky: 767 Bydliště: Brandýs nad Labem
|
Zaslal: 27. prosinec 2011, 12:10:45 Předmět: |
|
|
VODA> volani nevirtualni metody je v pohode vzdy (adresa metody je znama v dobe prekladu a jen se ji preda ukazatel na objekt a nic se nedereferencuje). Volani virtualni metody je v pohode, pokud je zarucene, ze ten objekt je nazivu (je potreba jit do tabulky virtualnich metod, takze tam se neco dereferencovat musi). _________________ http://trionteam.net |
|
Návrat nahoru |
|
 |
|