Halad Programozs Szlkezels szinkronizci V 1 0 OENIK
- Slides: 16
Haladó Programozás Szálkezelés + szinkronizáció V 1. 0 OE-NIK HP 1
Többszálú programok főbb lehetséges problémái • Versenyhelyzet („race condition”) – A párhuzamosan futó szálak kommunikációjához szinte biztosan szükség van közös erőforrások (memória (közös változók), portok, I/O eszközök, fájlok) használatára – Ha ezek állapotát egy szál módosítja, de közben más szálak is hozzájuk férnek, akkor az utóbbi szálak könnyen hibás vagy félkész adatokhoz juthatnak • Holtpont („deadlock”) – A szál olyan erőforrásra várakozik, ami sohasem érkezik meg – Két vagy több szál egymásra várakozik (így egyik sem fejeződik be soha) V 1. 0 OE-NIK HP 2
Versenyhelyzet demó • Készítsünk olyan programot, amiben több szál egy közös eredményt számol. (Pl: „együtt” elszámolnak 100000 -ig + Thread. Sleep-ek. ) • Készítsünk olyan konzolos programot, amiben több szál egy-egy saját eredményt számol, és az eredmény %-os állapotát saját színnel %-onként kiírják a konzolba V 1. 0 OE-NIK HP 3
Versenyhelyzet példák Szál 1 Szál 2 Eredeti kód t=x x=t+1 u=x x=u+2 1. lehetséges kimenetel (x értéke 0) t=x x = t + 1 (x értéke 1) 2. lehetséges kimenetel (x értéke 0) u=x t=x x=t+1 3. lehetséges kimenetel V 1. 0 u=x x = u + 2 (x értéke 2) (x értéke 0) t=x x = t + 1 (x értéke 1) OE-NIK HP u=x x = u + 2 (x értéke 3) 4
Versenyhelyzet • Sok nyelvi konstrukció használatából is adódhat versenyhelyzethez vezető állapot! • X++ – A ++ az utasítások szintjén különálló olvasás és írás műveletből áll. (Memóriából kiolvasásig jut el „A” szál, amikor jön „B” szál és pl. elvégzi az X növelését. „A” szál számára azonban az X még a memóriából kiolvasott értéket viseli) • X += 2 – A += az utasítások szintjén különálló olvasás és írás műveletből áll. Mint előbb. • A[i] += 1 – Előfordulhat, hogy másik szál épp ugyanezen indexre dolgozna (esetleg más néven). Mint előbb. • Természetesen magas szinten is létezik a probléma if (!list. Contains(key)) list. Add(key); Másik szál a két hívás lefutása között beillesztheti ugyanezt a kulcsot A példák forrása: http: //www. drdobbs. com/tools/avoiding-classic-threading-problems/231000499 V 1. 0 OE-NIK HP 5
Holtpont demó • Készítsünk olyan WPF-es programot, amely hosszú műveleten dolgozik, és az állapotát (eredmény kiszámolásának %-os állását) kiírja egy progressbar-ra • Legyen egy gomb, amit megnyomva Wait-eljünk rá az eredményt számoló taszkra, és ha az véget ért, írjunk ki valamit (pl: „az eredmény elkészült”) • Nem adatkötéssel csináljuk – Adatkötés esetén ugyanígy fellép a bemutatni kívánt probléma, csak a kiváltó okok nem láthatók V 1. 0 OE-NIK HP 6
Holtpont • Oka (példából): – Szál 1: hosszú műveletet végez, és néha Invoke()-ol, hogy kiírja az aktuális állapotát. – Főszál: a futás egy bizonyos pontján Join()/Wait()-val megpróbálja bevárni Szál 1 -et. – Következmény: Szál 1 éppen az Invoke()-ban van, tehát főszálra vár, amikor a főszál pedig a Join()/Wait() miatt éppen Szál 1 -re vár. • Klasszikus holtpont példa (kritikus szakasszal; magyarázat később): – Erőforrásokat lockkal próbáltunk védeni. Mindkét szál már belépett az első kritikus szakaszba, ott viszont várakoznia kell, hogy hozzájusson a másik lehetséges erőforráshoz. V 1. 0 1 lock (a) 2 { // feldolgozás 3 lock (b) 4 { 5 // feldolgozás 6 } 7 8 } 1. szál 1 lock (b) 2 { // feldolgozás 3 lock (a) 4 { 5 // feldolgozás 6 } 7 OE-NIK HP 8 } 2. szál 7
Versenyhelyzet és holtpont kivédése • Versenyhelyzet akkor áll fenn, amikor több szál próbál egyszerre azonos adathoz hozzáférni – Ha megoldható, ne használjunk a szálak számára közös objektumokat (referenciatípusok esetén különösen figyelni!) – Bizonyos feladatok/adatok esetén értéktípusok megfontolandók lehetnek – Ha ez nem megoldható, akkor szálszinkronizáció – De: OK a szálak számára közös adat, HA az elérés minden szál részéről readonly • A holtpont kivédésére nincs megoldás (alapos tervezés!) V 1. 0 OE-NIK HP 8
Szinkronizáció • A szálszinkronizáció biztosítja, hogy párhuzamosan egymás mellett futó szálak nem azonos időben hajtanak végre egy adott programszakaszt • Több formája van (kölcsönös kizárás, randevú) • Sok programozói munkát igényel, extrém módon hibaérzékeny, rosszul tesztelhető – Nem minden hiba jön elő minden esetben, minden konfiguráció mellett… • Lassít – Rossz tervezéssel gyakorlatilag sorossá redukálható a végrehajtás • Ha lehet, próbáljuk elkerülni (külön adat a szálaknak stb. ) – Sokszor nem lehet V 1. 0 OE-NIK HP 9
Szinkronizáció kölcsönös kizárással • Kritikus szakasz („critical section”) A programokon belül megjelölt kritikus kódrészletek soros végrehajtását biztosítja több párhuzamos szál esetén is. Amíg az egyik szál az „A” kritikus szakaszon dolgozik, a többi szál nem léphet be az „A” kritikus szakaszba. . NET osztályok: System. Threading. Monitor (és a C# „lock” utasítása), System. Threading. Mutex, System. Threading. Reader. Writer. Lock stb. • Szemafor („semaphore”) A kritikus szakasz általánosítása (többpéldányos erőforrások esetén egyszerre több szál belépését is lehetővé teszi). . NET osztály: System. Threading. Semaphore • Atomi végrehajtás („interlocked execution”) Egyes egyszerű műveletek oszthatatlan végrehajtását biztosítja (igen gyors). . NET osztály: System. Threading. Interlocked • Csővezeték („pipe”), konkurrens gyűjtemények V 1. 0 Olvasható és írható tároló, amely szükség szerint várakoztatja az igénylőket. (Az ún. „termelő-fogyasztó” probléma megoldására készült. ) 10. NET-ben: System. Collections. Concurrent osztályai
Szinkronizáció bevárással (randevú) • Esemény („event”) Lehetőséget ad alkalmankénti vagy rendszeres jelzésre (pl: szál jelzi, hogy végzett a feladatával). . NET osztályok: System. Threading. Auto. Reset. Event, System. Threading. Manual. Reset. Event stb. • Időzítő („timer”) Relatív vagy abszolút időhöz való igazodást tesz lehetővé. . NET osztályok: System. Windows. Forms. Timer, System. Timers. Timer, System. Threading. Timer stb. V 1. 0 OE-NIK HP 11
Példa szinkronizációra (a „lock” utasítás) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 V 1. 0 using System; using System. Threading; Figyelem: SOHA ne írjunk le az alábbiakra hasonlító kódot: class Program { private static int counter = 0; private static object lock. Object = new Object(); static void Main(string[] args) { Thread t 1 = new Thread(Thread. Method); t 1. Start(); Thread t 2 = new Thread(Thread. Method); t 2. Start(); } } lock (this) vagy lock (typeof(Program)) azaz sose lockoljunk olyat, amiről nem tudjuk befolyásolni, ki fér hozzá A lock utasítás nélkül a metódus sorosan (egy szálon futtatva) helyesen működik, párhuzamosan (több szálon) azonban nem private static void Thread. Method() { lock (lock. Object) { counter++; Thread. Sleep(500); Console. Write. Line("A számláló állása: " + counter); } } OE-NIK HP 12
Feladat • A és B barátságos számok, ha osztóösszegük kölcsönösen egyenlő a másik számmal • Vagyis: „A” osztóösszege (önmagát kihagyva) B „B” osztóösszege (önmagát kihagyva) A • Feladat: írjuk ki az összes barátságos számot 1 000 -ig a lehető leggyorsabban • Osztóösszegek meghatározása: – Szokványos módszerrel: Ciklus i=2 -től Gyök(X)-ig, minden osztót és osztópárt hozzáadok az összeghez sok osztás – Eratosthenes szita: a 2 -t mint osztót hozzá kell adni az osztóösszeghez a következő számoknál: 4, 6, 8, … A 3 -t mint osztót a 6, 9, 12 számoknál … etc V 1. 0 OE-NIK HP 13
Feladat Készítsünk többszálú konzolos alkalmazást, amely során két szál használja ugyanazt az erőforrást, amit esetünkben egy számokat tároló sor jelképez. Az egyik szál feladata a sor feltöltése, a másik feladata a sorból egy elem feldolgozása (kivétele). A fejlesztés közben gondoskodjunk a szálak szinkronizációjáról is! Ötletek: – Először egyszerű megvalósítással döntsük el, szükség van-e szinkronizációra, majd ha úgy ítéljük meg, hogy igen, akkor használjuk a lock utasítást vagy a Monitor osztály statikus Enter(), illetve és Exit() metódusát – Szinkronizáció esetén a jobb teljesítmény érdekében igyekezzünk a lehető legrövidebbre venni a kritikus szakaszt V 1. 0 OE-NIK HP 14
Megoldás V 1. 0 OE-NIK HP 15
Irodalomjegyzék • J. Richter: CLR via C#, Fourth Edition Kiadó: Microsoft Press, 2012 Web: http: //www. wintellect. com/ Nyelv: angol További források: MSDN, Miklós Árpád prezentációi V 1. 0 OE-NIK HP 16