Intro To .Net Threads

3,583 views

Published on

A brief compilation of notes on .NET threads .....

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,583
On SlideShare
0
From Embeds
0
Number of Embeds
44
Actions
Shares
0
Downloads
113
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Intro To .Net Threads

  1. 1. Introduction to threading in .NET
  2. 2. Traditional Win32 Processes <ul><li>A process is the set of resources (system libraries and primary thread ) and the memory allocations used by a running application . </li></ul><ul><li>For each *.exe loaded into memory, OS creates separate and isolated process </li></ul><ul><li>The failure of one process does not affect the functioning of another </li></ul><ul><li>Every Win32 process is assigned a unique Process Identifier or PID </li></ul>
  3. 3. Overview of threads <ul><li>Every Win32 process has exactly one main “thread” that functions as the entry point for the application </li></ul><ul><li>A thread is a path of execution within a process </li></ul><ul><li>The first thread created by the process entry point, or Main() is termed the 'primary thread' </li></ul><ul><li>The primary thread can be made to 'spawn' additional secondary threads using Win32 API functions like CreateThread()‏ </li></ul>
  4. 4. Overview of threads <ul><li>Each thread , primary or secondary , is a unique path of execution in the process and has concurrent access to all shared points of data </li></ul><ul><li>Using too many threads in a process, in a single CPU system , may actually DEGRADE performance since the CPU has to switch between the threads </li></ul><ul><li>Single CPU systems use 'time slice ' to service each thread for a unit of time. It provides 'Thread local storage' for each thread to maintain state between time slices </li></ul><ul><li>If a process does not have any foreground threads, the process ends , even if there are active background threads </li></ul>
  5. 5. Namespaces <ul><li>System.Threading.Thread represents managed thread </li></ul><ul><li>System.Diagnostics.ProcessThread represents OS thread </li></ul><ul><li>CLR introduced concept of a background thread. </li></ul><ul><li>UI threads are typically Windows forms threads, while worker threads are compute bound or IO threads. </li></ul>
  6. 6. Asynchronous delegates <ul><li>In .NET , usual pattern for implementing an asynchronous method call is for some object to expose two methods, BeginXXX() and EndXXX() where XXX is the name of the method </li></ul><ul><li>BeginXXX() is the method that is called to start the operation. It returns immediately , with the method left executing – on a thread pool thread </li></ul><ul><li>EndXXX() is called when the results are required . If the operation is still executing, EndXXX() waits until it is completed before returning the values </li></ul>
  7. 7. Asynchronous delegate design pattern <ul><li>Some of the .NET classes which inherently implement this pattern </li></ul><ul><li>System.IO.FileStream (BeginRead()/ EndRead())‏ </li></ul><ul><li>System.Net.WebRequest(BeginRequest() / EndRequest())‏ </li></ul><ul><li>System.Windows.Forms.Control (BeginInvoke() / EndInvoke())‏ </li></ul><ul><li>System.Messaging.MessageQueue (BeginReceive() / EndReceive())‏ </li></ul>
  8. 8. Asynchronous delegate design pattern <ul><li>You can asynchronously invoke any method in .NET by wrapping it in a delegate </li></ul><ul><li>Every delegate in .NET creates a BeginInvoke() and EndInvoke() method for a delegate </li></ul><ul><li>We will use the IAsyncResult interface, which has 4 important properties : </li></ul><ul><li>AsyncState is some data passed to callback method </li></ul><ul><li>AsyncWaitHandle is a locking mechanism </li></ul><ul><li>CompletedSynchronously is a boolean (completed on this thread ?)‏ </li></ul><ul><li>IsCompleted is a boolean (operation completed ?)‏ </li></ul>
  9. 9. CLR Threads <ul><li>Currently each logical CLR thread uses one physical Windows thread </li></ul><ul><li>In future the CLR may have its own threads , independent of the windows threads </li></ul><ul><li>So, .NET programmers should use CLR threads and not Windows threads </li></ul><ul><li>CLR threads can either be created explicitly using 'new Thread()' method , or implicitly (thread pool) when we invoke asynchronous operations </li></ul>
  10. 10. CLR Threads <ul><li>Some processes also use multiple threads for isolation. For example, the common language runtime ( CLR ) has a finalizer thread that wants to run in a predictable manner regardless of what some other thread happens to do. </li></ul>
  11. 11. History of Windows threads <ul><li>16 bit versions of Windows were single threaded , and if one application went into a loop , the entire system froze </li></ul><ul><li>Windows NT 3.1 was first multi threaded Windows OS, where each process got its own thread , and if that process looped, only that process froze and other processes ran </li></ul>
  12. 12. Efficiency of threads <ul><li>Threads are an overhead </li></ul><ul><li>For each thread, a thread kernel object has to be allocated and initialized </li></ul><ul><li>Creation of each thread allocates 1 MB of address space and another 12 KB for kernel mode stack </li></ul><ul><li>After creating a thread, Windows notifies every DLL in the process about this new thread </li></ul><ul><li>When a thread is destroyed , every DLL is again notified </li></ul>
  13. 13. Efficiency of threads <ul><li>In a single CPU computer only one thread can run at a time </li></ul><ul><li>So, in single CPU systems, Windows changes context to other threads every 20 milliseconds </li></ul><ul><li>This switching is called ' context switch ' </li></ul><ul><li>All this makes Windows slower than if it was on a single thread </li></ul>
  14. 14. Steps in Context switching <ul><li>Enter kernel mode </li></ul><ul><li>Save CPU registers in current threads kernel object </li></ul><ul><li>Acquire ' spin lock ' </li></ul><ul><li>Determine which thread to switch to </li></ul><ul><li>Release ' spin lock ' </li></ul><ul><li>Load to CPU registers from new threads kernel object </li></ul><ul><li>Leave kernel mode </li></ul>
  15. 15. Moral of story <ul><li>Limit usage of threads especially on single CPU systems </li></ul><ul><li>Threading on single CPU systems only makes systems slower due to context switching, and also takes up more memory for thread maintenance </li></ul><ul><li>However, as we begin to use multiple CPU chips we may have to use threading to extract better performance </li></ul><ul><li>Ideally speaking , there should never be more threads in existence than there are CPUs in your computer </li></ul>
  16. 16. Hyper threading and Multi core <ul><li>Chip makers use hyper threading and multi core as 2 manufacturing techniques </li></ul><ul><li>Hyper threading (Intel Xeon and Intel Pentium 4) has 2 logical CPU's on a single chip </li></ul><ul><li>Each logical CPU in Hyper threading has its own CPU register but shares a CPU cache between the 2 CPUs </li></ul><ul><li>Hyper threaded CPUs give 10 to 30% boost to performance (not 100%)‏ </li></ul>
  17. 17. Multi core <ul><li>A multi core chip (Intel Pentium D , AMD Athlon 64 X2) has two physical CPU's on it. </li></ul><ul><li>Better performance compared to Hyper threaded chips since each CPU has dedicated CPU registers and CPU cache </li></ul><ul><li>In future chips will come with even 4, 8, 16, or 32 CPUs in them. This is because chips have reached the limit to their speed . Only way to grow is to have more CPUs per chip . </li></ul>
  18. 18. CLR thread pool <ul><li>Since creating and destroying threads is expensive, CLR creates thread pools when we program asynchronous operations . </li></ul><ul><li>One thread pool per process , for all AppDomains in process </li></ul><ul><li>There is a thread pool queue , and if there are no threads in the pool , CLR creates one </li></ul><ul><li>CLR reuses same thread for all requests until it till it crosses some limit . Then another thread is added to pool </li></ul><ul><li>If a thread pool thread is idle for 2 minutes , it is killed . </li></ul><ul><li>Thread pool threads are all background threads </li></ul>
  19. 19. When to create dedicated thread <ul><li>If you want the thread to be in a particular state that is not so in Thread pool thread </li></ul><ul><li>If you want to run at a special priority </li></ul><ul><li>If you wanted a foreground thread so that process does not end till this thread ends </li></ul><ul><li>If the compute bound thread would be very long running </li></ul><ul><li>If you wanted to abort it prematurely </li></ul>
  20. 20. Thread pool limit <ul><li>Thread pool has ' worker threads ' and ' I/O threads ' </li></ul><ul><li>Worker threads are used when application asks thread pool to perform asynchronous compute bound operation </li></ul><ul><li>I/O threads are used to access a file, network server, database, web service, or other hardware device. </li></ul><ul><li>In .NET 2.0, max number of worker threads default is 25 per CPU , and max number of I/O threads is 1000 per CPU. </li></ul><ul><li>Try to avoid a worker thread calling an I/O thread since that can suspend operations till the I/O thread is over </li></ul>
  21. 21. Asynchronous operations <ul><li>To queue an asynchronous compute bound operation to the thread pool </li></ul><ul><li>Static boolean QueueUserWorkItem(WaitCallback callBack)‏ </li></ul><ul><li>Static boolean QueueUserWorkItem(WaitCallback callBack, Object state); </li></ul><ul><li>Static boolean unsafeQueueUserWorkItem(WaitCallback callBack, Object state); </li></ul><ul><li>A ' work item ' is the method identified by the CallBack parameter that will be called by the ThreadPool thread </li></ul>
  22. 22. System.Threading.Timer <ul><li>When you construct an instance of the Timer class , you are telling the CLR that you want a method of yours called back at a specified time by a Thread pool thread </li></ul><ul><li>One of the Timer constructors is </li></ul><ul><li>Public Timer(TimerCallback callback, Object state, Int32 dueTime, Int32 period)‏ </li></ul><ul><li>The callback parameter is the method that the thread should call after it has done its job </li></ul>
  23. 23. Three timers in .NET <ul><li>System.Threading's Timer class to perform periodic background tasks on another thread </li></ul><ul><li>System.Windows.Form's timer class to wake up and send messages to desired callback method. </li></ul><ul><li>System.Timer's timer class used if you want to place a timer on a design surface. Essentially same as System.Threading's timer. </li></ul>
  24. 24. Deadlocks <ul><li>A deadlock is a situation wherein two or more competing actions are waiting for the other to finish, and thus neither ever does. It is often seen in a paradox like 'the chicken or the egg'. </li></ul>
  25. 25. Livelocks <ul><li>As a real-world example, livelock occurs when two people meet in a narrow corridor, and each tries to be polite by moving aside to let the other pass, but they end up swaying from side to side without making any progress because they always both move the same way at the same time. </li></ul>
  26. 26. Thread Synchronization <ul><li>Thread synchronization is required when two or more threads might access a shared resource at the same time </li></ul><ul><li>A resource can be as simple as a block of memory or a single object , or it can be much more complex, like a collection object that contains thousands of objects inside it, each of which may contain other objects as well </li></ul>
  27. 27. Race conditions <ul><li>Thread T1 modifies resource R, releases its Write lock to R, retakes the Read lock to R and uses R. </li></ul><ul><li>During the interval between giving up the write lock and taking the read lock, thread T2 has modified the state of R. </li></ul>
  28. 28. CPU Cache latency <ul><li>CPU Caches to improve performance. However, the cache will flush to the memory only at periodical intervals. This can make multiple threads think that a field has different values at the same time. </li></ul><ul><li>Variables marked as 'Volatile' will overcome this problem. Microsoft's latest JIT compilers also overcome this problem irrespective of the non usage of Volatile keyword. </li></ul>
  29. 29. System.Threading.Interlocked <ul><li>Since most asynchronous operations are sharing integer variables, the Interlocked class provides Increment(ref varName), Decrement(ref varName), Add(ref varName) static methods to work in a thread safe manner </li></ul><ul><li>It also has Exchange() and CompareExchange() methods to exchange states </li></ul>
  30. 30. System.Threading.Monitor class <ul><li>Lock the critical section of code with a Enter(Object) and Exit(Object) block to lock those sections </li></ul><ul><li>When a thread calls the Enter() method it waits to have exclusive access rights to the object </li></ul><ul><li>When it exits, the next call to Enter() is serviced </li></ul>
  31. 31. The lock C# keyword <ul><li>An elegant alternative to Monitor.Enter() and Monitor.Exit()‏ </li></ul><ul><li>Syntax is lock (typeof (classname)) { code that needs to be thread safe } </li></ul>
  32. 32. SyncRoot pattern <ul><li>Since Monitor and Lock can be applied from outside the class, effectively locking a portion of the class, it is better to create a private member within the class, and lock that : </li></ul><ul><li>Private objectInstanceSyncRoot = new Object(); </li></ul><ul><li>Lock (instanceSyncRoot) { code that needs to be thread safe } </li></ul>
  33. 33. Mutex (Win32 Thread lock mechanism)‏ <ul><li>Mutually Exclusive lock </li></ul><ul><li>Close to the use of Monitor with a few differences like same mutex can be used in several processes , but Monitor does not allow waiting on several objects </li></ul>
  34. 34. Semaphore (Win32 locking)‏ <ul><li>Similar to Mutex but uses a counter to keep track of how many threads are accessing a particular resource. So it allows a certain number of threads to access a resource simultaneously </li></ul>
  35. 35. Windows kernel objects for thread synchronization <ul><li>The CLR exposes Win32 objects for thread synchronization. However, these are to be avoided since Managed to unmanaged is extremely slow </li></ul><ul><li>WaitHandle </li></ul><ul><li>Mutex </li></ul><ul><li>Semaphore </li></ul><ul><li>EventWaitHandle </li></ul><ul><li>AutoResetEvent </li></ul><ul><li>ManualResetEvent </li></ul>
  36. 36. Events <ul><li>To have a threadpool thread call your callback method when a kernel object becomes signaled </li></ul><ul><li>Microsoft realized that many threads are spawned just to wait on other threads . WaitEvents are meant to handle this kind of events. The RegisterWaitForSingleObject can act on a Semaphore, or a Mutex, or a AutoResetEvent or a ManualResetEvent object </li></ul>
  37. 37. Thread synchronization <ul><li>Adding thread synchronization to your code makes the code run slower , hurting performanc e and reducing scalability </li></ul><ul><li>Writing thread synchronization code is difficult, and doing it incorrectly can lead to resources in inconsistent states causing unpredictable behavior </li></ul>
  38. 38. Windows Thread synchronization <ul><li>Interlocked functions </li></ul><ul><li>Mutexes </li></ul><ul><li>Semaphores </li></ul><ul><li>Events </li></ul><ul><li>Critical sections </li></ul>
  39. 39. .NET Thread Synchronization <ul><li>Monitor </li></ul><ul><li>ReaderWriter Lock </li></ul><ul><li>C# Lock </li></ul><ul><li>WaitHandle </li></ul><ul><li>SpinWait </li></ul>
  40. 40. Resources <ul><li>CLR Via C# - Jeffrey Richter </li></ul><ul><li>Concurrent Affairs column in MSDN magazine – Jeffrey Richter </li></ul>

×