1 / 98

Programowanie Aplikacji Lokalnych w Środowisku .NET

Programowanie Aplikacji Lokalnych w Środowisku .NET. Synchronizacja Obiekty synchronizacyjne Pula w ątków MS Parallel Computing Initiative Operacje asynchroniczne. Synchronizacja. Nieprzerywalne operacje Ochrona sekcji krytycznej Odmiany semaforów

zihna
Download Presentation

Programowanie Aplikacji Lokalnych w Środowisku .NET

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. ProgramowanieAplikacjiLokalnychw Środowisku .NET Synchronizacja Obiektysynchronizacyjne Pula wątków MS Parallel Computing Initiative Operacjeasynchroniczne

  2. Synchronizacja • Nieprzerywalneoperacje • Ochronasekcjikrytycznej • Odmianysemaforów • Inneobiekty o własnościachsemaforów • Innemetodysynchronizacji

  3. Synchronizacja • synchronizacja - szeregowanie w czasieoperacjiwątków Należyunikać! • aktywnegoczekaniajakometodysynchronizacji (SpinLock, SpinWait?) • Uśpieniewątku: Thread.Sleep(TimeSpan) • Najprostszysposóboczekiwanianakoniecwątku - Thread.Join(TimeSpan)

  4. Synchronizacja w trybie użytkownika • Dużomniejkosztownaniżwykorzystanieobiektówjądralock:Mutex ~ 1:50 • Możliwe jest synchronizowanietylkowątkówtegosamegoprocesu • Funkcjeatomowe: • InterlockedIncrement, • InterlockedDecrement, • InterlockedExchancheAdd, • InterlockedExchanche, (32bit) • InterlockedExchanchePointer, (64bit) • InterlockedCompareExchanche • .NET - class Interlooked • CompareExchange, Decrement, Exchange, Increment

  5. Sekcja krytyczna • Synchronizacja w trybieużytkownika • Możliwe jest synchronizowanietylkowątkówtegosamegoprocesu • Uwagawykonanie „wait” możespowodować – zmianętrybu Typobiektu: CRITICAL_SECTION Operacjenasekcjikrytycznej: • InitializeCriticalSectioninicjalizacjasekcjikrytycznej • DeleteCriticalSectionzwolnieniesekcjikrytycznej • EnterCriticalSectionwejście do sekcjikrytycznej • LeaveCriticalSectionwyjście z sekcjikrytycznej • TryEnterCriticalSectionsprawdzeniesekcjikrytycznej • .NET: Monitor

  6. Sekcjakrytyczna – C# - lock lock (x){ .... } System.Threading.Monitor.Enter(x); try { ... } finally { System.Threading.Monitor.Exit(x); } • Kontekst pozwala identyfikować poszczególne instancje sekcji krytycznej • Abyuzyskaćglobalnykontekstmożnaskorzystać z konstrukcjitypeofnp. lock(typeof(myObject)) synchronizowalnewrapery do zmiennychnp. HashtablemyHT = new Hashtable(); HashtablemySyncHT = Hashtable.Synchronized(myHT);

  7. Dostęp do zmiennych Thread Local Storage LocalDataStoreSlotlds = Thread.GetNamedDataSlot("COOKIE"); Thread.SetData(lds, "abc"); var napis = (string) Thread.GetData(lds); Synchronizowalnewrapery do zmiennychnp. HashtablemyHT = new Hashtable(); HashtablemySyncHT = Hashtable.Synchronized(myHT); lock(mySyncHT.SyncRoot) { foreach (Object item inmySyncHT) { // to do smthg }

  8. Obiekty synchronizacyjne Synchronizacja w trybie jądra jest dużo bardziej kosztowna • Odmiany semaforów • Mutex – semafor binarny • Semaphore – semafo wielowartościowy • Event – zdarzenie • Waitable timer – budzik: NT, 2K, XP • powiadomienie o zmianie w systemie plików • Obiekty, które mają własności semaforów: • proces, wątek - sygnalizowane po zakończeniu • zadanie - sygnalizowane po wyczerpaniu limitu czasu • plik - sygnalizowane gdy nie trwają operacje we/wy • wejściekonsoli - sygnalizowane gdy są jakieś znaki w buf.

  9. Nazwy obiektów synchronizacyjnych • korzystanie z jednego obiektu przez różne procesy • małe i duże litery są rozróżniane • długość nieprzekraczająca _MAX_PATH • znaki dozwolone takie jak dla nazwy pliku (bez \) • obiekty synchronizacyjne dzielą tę samą przestrzeń nazw • przestrzeń nazw dla obiektów synchronizacyjnych jest rozłączna z przestrzenią nazw systemu plików

  10. Obiekt synchronizacyjny • obiektprzyjmującystany • signaled – semaforpodniesiony • not signaled– semaforopuszczony • operacje • zasygnalizowanie (podniesieniesemafora - funkcjededykowanedlatypuobiektu • likwidacjastanuzasygnalizowanego (opuszczeniesemafora) – funkcjewspólnedlawszystkichtypówobiektów

  11. Opuszczanie semafora • opuszczeniepojedynczegosemafora DWORD WaitForSingleObject (HANDLE hObject, DWORD dwMiliseconds) ; INFINITE • opuszczaniezbiorusemaforówDWORD WaitForMultipleObjects(DWORD nCount, CONST HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMiliseconds) • Oczekiwanieprzerywanekomunikatami MsgWaitForMultipleObjects • Oczekiwanieprzerywaneoperacjami I/O WaitForSingleObjectEx((HANDLE hObject, DWORD dwMiliseconds, BOOL bAlertable) ; WaitForMultipleObjectsEx, MsgWaitForMultipleObjectsEx SignalObjectAndWait(HANDLEhObjectToSignal,HANDLE hObjectToWait, DWORD dwMiliseconds, BOOL bAlertable) ;

  12. Opuszczanie semafora .NET class WaitHandle {public virtual Boolean WaitOne();public static Boolean WaitAll(WaitHandle[]);public static Boolean WaitAny(WaitHandle[]);…public virtual Boolean WaitOne(int, bool);public virtual Boolean WaitOne(TimeSpan, bool);public virtual Boolean SignalAndWait (WaitHandle, WaitHandle) public virtual Boolean SignalAndWait (WaitHandle, WaitHandle, TimeSpan, Boolean);public virtual IntPtrHandle { get; set; }public SafeWaitHandleSafeWaitHandle { get; set; } };

  13. Opuszczanie semafora .NET class ManualResetEvent : WaitHandle; class AutoResetEvent : WaitHandle; class Mutex : WaitHandle; class Semaphore : WaitHandle;

  14. Event • Zdarzenie - obiektdwustanowy, służący do sygnalizowaniazajściawydarzenia • Synchronizacjawątkówdowolnychprocesów • Typyzdarzeń • manual-reset event -podniesieniewznawiawszystkiewątki • automatycznieopuszczane - podniesieniewznawiazawszejedenwątek • Operacjenazdarzeniu • CreateEvent(PSECURITY_ATRIBUTE psa, BOOL bManual, BOOL bInitial, PCSTR pszName) • OpenEvent • SetEvent - podniesienie • ResetEvent - opuszczenie • PulseEvent - podniesienieiopuszczenie - zwalniawszystkieczekającewątki (manual) lubjeden(auto) • .Net: AutoResetEvent, ManualResetEventAutoResetEventSlim, ManualResetEventSlim (.Net 4.5)

  15. Mutex • Semaforbinarny - obiektdwustanowy • Umożliwiasynchronizacjęwątkówdowolnychprocesów • Podniesieniesemaforabinarnegowznawiatylkojedenwątek • Mutex jest własnościąwątku: • wąteknieczekanazajętymjużprzezsiebieMutexie, ale trzebaodpowiedniąliczbęrazywołaćReleaseMutex) • podnieśćMutexamożetylkowątek, który go opuścił (dlainnychwątkówReleaseMutexniedajeefektu) • zakończeniewątkubędącegowłąścicielemmuteksapodnosi ten semafor -> wynikWaitFor... = WAIT_ABANDONED • Operacjenasemaforzebinarnym • CreateMutex (PSECURITY_ATRIBUTE psa, BOOL bInitialOwned, PCSTR pszName) • OpenMutex • ReleaseMutexpodniesienie, opuszczaniesemafora: WaitFor... • .NET:Mutex

  16. Semaphore • Semaforwielowartościowycechujeograniczonaliczbastanów (0 oznaczasemaforopuszczony) • Próbaopuszczeniasemaforzmniejszalicznik o 1 • Podniesieniesemaforazwiększalicznikiwznawiatylewątków, o ilezostałzmniejszonylicznik • Opuszczenieipodniesieniemożebyćwykonaneprzezróżnewątki • operacjenasemaforzewielowartościowym • CreateSemaphore(PSECURITY_ATRIBUTE psa, LONGlInitialCount, LONGlMaximumCount, PCSTR pszName) • OpenSemaphore • ReleaseSemaphorepodniesienie • .NET: Semaphore, SemaphoreSlim(>=.Net 4.0 – zalecany, pracujehybrydowotj. nieuzywa obj. jądrapókinie jest to konieczne)

  17. .NET: xxxSlim • Obiektypracujace w obrębiejednegoprocesu • SemaphoreSlim (5x(?) mniejszynarzut) • ReaderWriterLockzastąpionyprzezReaderWriterLockSlim

  18. .NET: ReaderWriterLockSlim • Semafordedykowanydlaasymetrycznejsytuacjigdzeistniejemożliwośćwieluodczytówvs. dostępwyłączny • operacjenasemaforze • IsReaderLockHeld, IsWriterLockHeld • WriterSeqNum • AcquireReaderLock, AcquireWriterLock • AnyWritersSince • UpgradeToWriterLock, DowngradeFromWriterLock • ReleaseReaderLock, ReleaseWriterLock • RestoreLock, ReleaseLock.

  19. .NET: Barrier Barrier jest obiektem synchronizacyjnym, który pozwala na zatrzymanie wykonania większej liczby wątków w określonym punkcie dopóki nie zostanie on osiagnięty przez wszystkie wątki Dennis Mac Charlie Gas Station = Barrier Boston

  20. Barrier - kod var delay = TimeSpan.FromSeconds(1); varcharlie = new Thread(() => DriveToSeattle("Charlie“, delay)); charlie.Start(); varmac = new Thread(() => DriveToSeattle("Mac", delay)); mac.Start(); vardennis = new Thread(() => DriveToSeattle("Dennis", delay)); dennis.Start(); charlie.Join(); mac.Join(); dennis.Join();

  21. Barrier - kod static void DriveToSeattle(string name, TimeSpantimeToGasStation) { // Drive to gas station Console.WriteLine("[{0}] Leaving House", name); Thread.Sleep(timeToGasStation); Console.WriteLine("[{0}] Arrived at Gas Station", name); // Need to sync here // Perform some more work Console.WriteLine("[{0}] Leaving for Seattle", name); }

  22. Barrier - kod static Barrier sync = new Barrier(3); static void DriveToSeattle(string name, TimeSpantimeToGasStation) { // Drive to gas station Console.WriteLine("[{0}] Leaving House", name); Thread.Sleep(timeToGasStation); Console.WriteLine("[{0}] Arrived at Gas Station", name); // Need to sync here sync .SignalAndWait(); // Perform some more work Console.WriteLine("[{0}] Leaving for Seattle", name); }

  23. .NET: CountdownEvent CountdownEventjest obiektem synchronizacyjnym który pozwala śledzić wykonanie wiekszej liczby zadań i sygnalizować ich zakończenie. JOIN FORK Master Thread Master Thread Parallel Region

  24. CountdownEvent - Kod public static void DoShoping(int id) { Thread.SpinWait(2000000); Console.WriteLine("Customer {0} finished",id); } varsyncEvent = new CountdownEvent(1); foreach (int id in Enumerable.Range(1,20)) { intcurrentId = id; syncEvent.AddCount(); ThreadPool.QueueUserWorkItem(delegate { DoShoping(currentId); syncEvent.Signal(); }); } syncEvent.Signal(); syncEvent.Wait(); Console.WriteLine("All customers finished Shopping");

  25. Powiadomienie o zmianie w systemieplików • powiadomienie jest semaforem, któryzmieniastannapodniesiony w chwiliwystąpieniazmiany w systemieplików • zleceniedokonaniapierwszegopowiadomienia HANDLE FindFirstChangeNotification( LPTSTR lpszPath, // ścieżka BOOL fWatchSubTree, // czyzmianapoddrzewa DWORD fdwFilter) ; // rodzajzmiany • FindNextChangeNotification - zleceniedokonaniakolejnegopowiadomienia • FindCloseChangeNotification - rezygnacja • WaitFor... - oczekiwanienapowiadomienie • .NET: System.IO.FileSystemWatcher

  26. Inne metody synchronizacji • WaitForInputIddle(HANDLE hProcess, DWORD wMillisecinds) • .NET : System.Diagnostics.Process.WaitForInputIdle Czekaażwątekgłównyprzetworzywszystkiekomunikaty (np. emulacjanaciśnięćklawiszy)

  27. O mierzeniuczasu • Sleep(x) • System.Threading.Timer(inny wątek via ThreadPool) • System.Timers.Timer(inny wątek) • Dedykowanedlaokien: • System.Windows.Forms.Timer(WindowsForms) • System.Windows.Threading.DispatcherTimer (WPF) • Waitable timer

  28. Waitable timer - NT/2K/XP • budzik jest obiektemczasu, który jest sygnalizowanypoupływieokreślonegoczasu (jednorazowolubcyklicznie) • typybudzików • jednokrotne, cykliczne • sposóbopuszczania • ręczneopuszczane- podniesieniewznawiawszystkiewątki • synchronizacja - podniesionywznawiatylkojedenwątek • operacjenabudziku • CreateWaitableTimer(PSECURITY_ATRIBUTEpsa, BOOL bInitialOwned, PCSTR pszName) • OpenWaitableTimer • SetWaitableTimer (HANDLE hTimer, const LARGE_INTEGER *pDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletitionRoutine, PVOID pvArgToCompletitionRoutine, BOOL fResume) • CancelWaitableTimer - zatrzymanie • .Net 4.5 ~ Task.Delay(milliseconds)

  29. .NET vs API • Wołaniefunkcjiunmanage – wymagaichzaimportowania: [DllImport("msvcrt.dll")] using System; using System.Runtime.InteropServices; class PlatformInvokeTest { [DllImport("msvcrt.dll")] public static extern intputs(string c); [DllImport("msvcrt.dll")] internal static extern int_flushall(); public static void Main() { puts("Test"); _flushall(); } } MSDN -> Platform Invoke Tutorial

  30. System.Threading.Timer Class Timer { ... public Timer (TimerCallback); public Timer (TimerCallback, Object, TimeSpan, TimeSpan); public Timer.Change (TimeSpan, TimeSpan); ... }; • F.callbacku jest obsługiwanaprzez thread pool

  31. .NetWaitableTimer .Net 4.5 Task.Delay(milliseconds) .Net 4.0

  32. DeadLock object l1 = new object(); object l2 = new object(); new Thread (() => { lock (l1) { Thread.Sleep (1000); lock (l2); // Deadlock } }).Start(); lock (l2) { Thread.Sleep (1000); lock (l1); // Deadlock }

  33. DeadLock - zapobieganie • Zajmowaniezasobów w takiejsamejkolejności • UżycieWaitAll

  34. Leniwainicjalizacja class Foo { Expensive _expensive; public Expensive Expensive { // Lazily instantiate Expensive Get { if (_expensive == null) _expensive = new Expensive(); return _expensive; } } ... } lock

  35. TLS static ThreadLocal<int> _x = new ThreadLocal<int> (() => 3); varlocalRandom = new ThreadLocal<Random>( () => new Random (Guid.NewGuid().GetHashCode()) );

  36. TLS class Test { LocalDataStoreSlot _secSlot = Thread.GetNamedDataSlot ("securityLevel"); intSecurityLevel { get { object data = Thread.GetData (_secSlot); return data == null ? 0 : (int) data; // null == unintl. } set { Thread.SetData (_secSlot, value); } } ... }

  37. Wielozadaniowość w .NET

  38. Kosztwątku: • Pamięć: • Obiektjądra (1.2 kB) • Thread environment block (4/8 kB 32/64b) • Stos (trybużytkownika 1MB) • Stos (trybjądra 12/24kB dla 32/64b) • DllMain -> DLL_THREAD_ATTACH/ DLL_THREAD_DETACH • Wniosek: wątkikosztująinienależyichnadużywać

  39. Wątki Wątek CLR == wąteksystemowy(jakdotąd) Start nowegowątku: • new Thread (() => { } ).Start(); • new Thread (() => { } ).Start(startState); Jaki będzie wynik dla: for (int i = 0; i < 10; i++) new Thread (() => Console.Write (i)).Start();

  40. Wątki Wątek CLR == wąteksystemowy(jakdotąd) Start nowegowątku: • new Thread (() => { } ).Start(); • new Thread (() => { } ).Start(startState); Jaki będzie wynik dla: for (int i = 0; i < 10; i++) new Thread (() => Console.Write (i)).Start(); a dla for (inti = 0; i < 10; i++) { int temp = i; new Thread (() => Console.Write (temp)).Start(); }

  41. Wątki Kiedyużywać: • długiezadania, • priorytetinnyniż normal • zadania foreground

  42. Pula wątków - .NET • Obiektsystemowy: ThreadPool • Uruchamianiedla void: ThreadPool.QueueUserWorkItem (notUsed => Console.WriteLine ("Msg from pool")); • lubdlazwrotu (alternatywniemożnazdef. f. callb.) static int Work (string s) { return s.Length; } … Func<string, int> method = Work; IAsyncResult cookie = method.BeginInvoke ("test", null, null); … int result = method.EndInvoke (cookie); Console.WriteLine (“Result: " + result);

  43. Pula wątków - .NET • Kiedyużywać: • krótkiezadania (<250ms, idealnie<100ms), • priorytet normal, • zadania background • ThreadPool.Set[Max|Min]Thread nowewątkisąalokowaneod Min do Max jeśliprzezjakiśczas (0.5s) niezmieniasiękolejkazadań do wykonania. • Używaneprzez : WCF, Remoting, ASP.NET, and ASMX Web Services, System.Timers.TimeriSystem.Threading.Timer, BackgroundWorkerasynchr. delegaty

  44. Wątki, pula Pot. problemy: • Odebranieiprzekazanieew. wyjątków • Czekanienawątek (synchronizacja) blokujeinnywątek • Czekanie: new Thread (() => Console.Write (“test”)).Start().Join(); • lub varendOfWork = new CountdownEvent(10); for (vari=1; i<=10; i++) new Thread (() =>endOfWork.signal()).Start(); endOfWork.wait();

  45. Czekanieinaczej var threads = new list<Thread>(); for (vari=1; i<=10; i++) { var t = new Thread (() =>endOfWork.signal()); t.Start(); threads.Add(); } WaitHandle.WaitAny(threads, true); // false ?

  46. Parallel Extensions .Net 4.x • .NET Library • Mogą być wykorzystywane we wszystkich językach na platformie .NET • Obejmuje 3 różne elementy • Parallel LINQ (PLINQ) • Task Parallel Library (TPL) • Coordination Data Structures (CDS)

  47. Od watków do zadań (1) static void Main() {Tree tr = Tree.CreateSomeTree(9, 1);Stopwatch sw = Stopwatch.StartNew();WalkTree(tr);Console.WriteLine("Elapsed= " + sw.ElapsedMilliseconds.ToString());Console.ReadLine(); } static void WalkTree(Tree tree) { if (tree == null) return; WalkTree(tree.Left); WalkTree(tree.Righ); ProcessItem(tree.Data); }

  48. Od watków do zadań (2) static void WalkTree(Tree tree) { if (tree == null) return; Thread left = new Thread((o) => WalkTree(tree.Left)); left.Start(); Thread righ = new Thread((o) => WalkTree(tree.Righ)); righ.Start(); left.Join(); righ.Join(); ProcessItem(tree.Data); }

  49. Od watków do zadań (3) static void WalkTree(Tree tree) { if (tree == null) return; Task left = new Task((o) => WalkTree(tree.Left)); left.Start(); Task righ = new Task((o) => WalkTree(tree.Righ)); righ.Start(); left.Wait(); righ.Wait(); ProcessItem(tree.Data); }

  50. Parallel LINQ-to-Objects (PLINQ) • Wykorzystuje model "Task" • Pozwala na wykorzystanie wielu rdzeni przy zapytaniach LINQ • Wspiera w pełni standardowe operatory zapytań • Minimalizuje wpływ na istniejące zapytania LINQ var q = from p in people         where p.Name == queryInfo.Name && p.State == queryInfo.State && p.Year >= yearStart && p.Year <= yearEnd orderbyp.Year ascending         select p; .AsParallel()

More Related