Multi-Threading
Upcoming SlideShare
Loading in...5
×
 

Multi-Threading

on

  • 3,409 views

Slide deck from my presentation on multi-threading with .NET. The presentation covers from beginner onwards and looks at current technologies (i.e. pre .NET 4.0) specifically. ...

Slide deck from my presentation on multi-threading with .NET. The presentation covers from beginner onwards and looks at current technologies (i.e. pre .NET 4.0) specifically.

What makes this extra special is the entire process of how I prepared for it, from finding content to slide deck layout to presentation prep is documented at: http://www.sadev.co.za/content/how-i-build-presentations-series-index

Statistics

Views

Total Views
3,409
Views on SlideShare
3,404
Embed Views
5

Actions

Likes
1
Downloads
57
Comments
0

1 Embed 5

http://www.slideshare.net 5

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Initially do finding primes then speed it up with simple threadingDemo notes – get someone to note the times in milliseconds and maybe run twice to get an average. Also note the amount of primes (should always 9593, within first 100000) being displayed in test 2 may differ between runs – this is important to point out as it leads to the next topicAlso get task monitor open for this set – show the difference between using one and two cores (from test 1 to test 2)All demos should be run in release mode (Ctrl+F5) unless otherwise specifiedOpen up the base threading solution, go over the core code of demo set 1.Paste in line Ctrl+1 within the loopText should be: TestPrime(primeCounter);Run, show results, explain the problem domain and these can be worked out individuallyPaste in line Ctrl+2 – replacing the text within the loop. Text should be: new Thread(new ParameterizedThreadStart(TestPrime)).Start(primeCounter);Should have an exception on the TestPrime because it’s signature does not match.Paste in line Ctrl+3 below the main method, should be ok to run now.Text should be: private static void TestPrime(object objectToTest) { int valueToTest = Convert.ToInt32(objectToTest); TestPrime(valueToTest);}-< END >-
  • Fixing the code by adding synchronisationFirst step add code in Ctrl+4, replacing existing thread start, and explain properties and that maybe (ha ha) if we up the priority it will help – might be good point to wake the audience to see who thinks it will.Text should be: Thread primeThread = new Thread(new ParameterizedThreadStart(TestPrime)); primeThread.Name = primeCounter.ToString(); primeThread.Priority = ThreadPriority.Highest; primeThread.Start(primeCounter);Note that by now we should have a few different numbers of found primesNext add code from Ctrl+5, to the variables at the top – the idea here is to add items to the “gate” and remove them once calculated and do not finish until all the numbers are worked outText should be: private static List gate = new List();Ctrl+6 into the loop above the code from beforeText should be: gate.Add(primeCounter);Ctrl+7 into the overrided TestPrime method we added before, at the endText should be: gate.Remove(valueToTest);Add the next code, Ctrl+8, after the loop so that we are forced to wait until the gates have been clearedRun in debug mode and wait for the crash – the list is being manipulated in an odd way and the item was gone before we could get it.Right now explain we need to make sure that only one thread at a time can access the list to fix it.Ctrl+9 to the variablesText should be: private static object locker = new object();Replace the gate.add and gate.remove we added eariler with the code from Alt+1 and Alt+2 respectivelyText (Alt+1) should be: lock (locker) { gate.Add(primeCounter); }Text (Alt+2) should be: lock (locker) { gate.Remove(valueToTest); }Run in release and note the time and itemsExplain that the amount of threads is hurting the CPU, increasing deadlocks etc… so lets limit the treads Add Alt+3 after the lock for adding to the gate, but before we spin up a threadText should be: while (gate.Count > 10) { Thread.Sleep(0);}-< END >-
  • This is used for lock-free code - making sure that changes made on one thread are visible to another without incurring the cost of a lock. It does not control thread synchronization, unlike lock
  • Volatile DemoCLR memory model… Essentially the memory model allows for non-volatile readswrites to be reordered as long as that change can not be noticed from the point of view of a single thread. The issue is, of course, there is often more than one thread (like the finalizer thread, worker threads, threadpool threads, etc). volatile essentially prevents that optimization. Replace the two variables we added in the last demo with the new one in Alt+4Text should be: private static int poolSize;Replace the gate.add (lock and all with) the interlocked from Alt+5Text should be: Interlocked.Increment(ref poolSize);Replace the while on the gate with the code from Alt+6Text should be: while (poolSize > 10) { Thread.Sleep(0); }Replace the gate.remove (lock and all) with the interlocked code from Alt+7Text should be: Interlocked.Decrement(ref poolSize);Replace the check at the end of the loop with code from Alt+8Text should be: while (poolSize > 0) { Thread.Sleep(0); }Run and check the speed increase, if any-< END >-
  • Using ThreadPool to find primesNow replace all the code in the main loop, with the exception of the Interlocked.Increment with Alt+9Text should be: ThreadPool.QueueUserWorkItem(TestPrime, primeCounter);RUN-< END >-
  • WinForms DemoStart off explaining what we are trying to do – we have fully working SINGLE threaded solution going on here. First step is to make the status bar keep track of what we are doing.Add backgroundWorker control and add a DoWork event, and in there add the code from Ctrl+Alt+1Text should be: while (true) { toolStripStatusLabel.Text = primesList.Items.Count.ToString(); Thread.Sleep(250); }Add the kick off, Ctrl+Alt+2, to the form constructor below the initialisationText should be: backgroundWorker.RunWorkerAsync();RUNNow remove the background worker component and related code. Add the following code to the class (Ctrl+Alt+3)Text should be: private void timerTick(object state) { toolStripStatusLabel.Text = primesList.Items.Count.ToString(); }And add Ctrl+Alt+4 to the constructorText should be: System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(timerTick), null, 0, 100);RUN-< END >-
  • Add the code from Ctrl+Alt+5 to the loop replacing the code which calls TestprimeText should be: ThreadPool.QueueUserWorkItem(ThreadedTestPrime, primeCounter);Run and crashNow add Ctrl+Alt+6 to the isPrime block – lots of explaining needed now. Remove the add to list line.Text should be: AddItemDelegate addItemMethod = new AddItemDelegate(AddItem); this.Invoke(addItemMethod, valueToTest);Now add Ctrl+Alt+7 outside of any methodText should be: delegate void AddItemDelegate(int value);Run – point out that although we are doing a separate thread it is still not very responsive etc…Add Ctrl+Alt+8 to the new AddItem method we added previouslyText should be: Application.DoEvents();
  • Notification of every DLL in the process is on creation AND destruction
  • A race condition occurs when two threads access a shared variable at the same time. The first thread reads the variable, and the second thread reads the same value from the variable. Then the first thread and second thread perform their operations on the value, and they race to see which thread can write the value last to the shared variable. The value of the thread that writes its value last is preserved, because the thread is writing over the value that the previous thread wrote.
  • Show the debugging window for threading (if you it is gone, it is under Debug > Windows > Threading)Output window for debugging messages-< END >-

Multi-Threading Multi-Threading Presentation Transcript

  • Multi-Threading
  • .NET Multi-Threading
    Introductory Usage
    Proven Practices
    Overture
  • Hello to the threading world
  • Blocking
    Thread.Sleep & Join
    Locking
    lock, Mutex & Semaphore
    Singling
    EventWaitHandle& Wait/Pulse
    Non-Blocking
    Memory Barrier, Interlocked & Volatile
    Managing
  • Managing threads
  • static void Main()
    {
    Threadt = newThread (delegate() {
    Console.ReadLine(); });
    t.Start();
    t.Join(); // Wait until thread finishes
    /* Do next step */
    }
    Join
  • lock(locker)
    {
    gate.Add(primeCounter);
    }
    Monitor.Enter(locker);
    try
    {
    gate.Add(primeCounter);
    }
    finally
    {
    Monitor.Exit(locker);
    }
    Sugary lock
  • Same as a lock
    Advantage: Can work across processes, meaning multiple applications can use a single mutex
    Mutex
  • staticEventWaitHandle wh = new AutoResetEvent(false);
    static void Main() {
    newThread (Waiter).Start();
    Thread.Sleep (1000); // Wait for some time...
    wh.Set(); // OK - wake it up
    }
    static void Waiter() {
    Console.WriteLine("Waiting...");
    wh.WaitOne(); // Wait for notification
    Console.WriteLine("Notified");
    }
    Signalling
  • lock(locker)
    {
    gate.Add(primeCounter);
    }
    Thread.MemoryBarrier();
    try
    {
    gate.Add(primeCounter);
    }
    finally
    {
    Thread.MemoryBarrier();
    }
    Memory Barrier
  • static void Main() {
    Thread t = new Thread(delegate() {
    try {
    Thread.Sleep(Timeout.Infinite); // This is blocking
    }
    catch (ThreadInterruptedException) {
    Console.Write("Forcibly ");
    }
    Console.WriteLine("Woken!");
    });
    t.Start();
    t.Interrupt();
    }
    Interrupt
  • Similar usage to Interrupt
    Throws – ThreadAbortException
    Does not wait for blocking
    Abort
  • Using non-blocking management
  • Using the built in ThreadPools
  • Single thread pool per process
    Built in logic to grow and shrink pool
    Built-in Limits
    Worker threads – 25 per CPU
    I/O threads – 1000 per CPU
    Thread Pools
  • Threaded controls in WinForms
  • Timers
    Source Alex Calvo - http://msdn.microsoft.com/en-us/magazine/cc164015(printer).aspx
  • Talking to the UI thread from a worker thread
  • “Multi-threaded programming needs a little care”
    Patricia Shanahan
    Understatement?
  • Cost
    Thread Safety
    Race conditions
    Dead locks
    Exception Management
    Debugging
    Common Problems
  • 1 Mb of Address space
    12k for kernel mode stack
    Notification of every DLL in the process
    Threads are expensive
  • Reads value (5)
    Adds 1 – (6)
    Assumes value 6
    Reads value (6)
    Adds 1 – (7)
    Assumes value 7
    Thread 1
    Thread 2
    Race Conditions
  • If file does not exist
    Create it
    Populate it with initial data
    Read data from file
    Process data
    Write to file
    Logical Process I
  • If file does not exist
    Create it
    Populate it with initial data (Write Lock)
    Read data from file (Read Lock)
    Process data
    Write to file (Write Lock – if needed)
    Release locks
    Logical Process II
  • Creates file
    Locks writer
    Attempts to lock reader
    Waits…
    Locks Reader
    Processes data
    Attempts to lock writer
    Waits…
    Thread 1
    Thread 2
    Dead Locks
  • Exceptions are limited to a thread
    Exceptions
    Main
    Child
    try
    {
    }
    catch
    {
    }
    1
  • Debugging in Visual Studio
  • Threads are expensive – use wisely
    Use managed threads over native threads.
    Use Timers or ThreadPool where possible.
    Or the new parallel extensions in .NET 4.0
    Avoid mutex, unless you need cross process.
    Avoid Thread.Abortas it can have high side effects
    Avoid Thread.Suspend/Resume as a blocking system
    Rather use lock
    Proven Practises I
  • Be careful what you lock
    lock’s are type based shared across all AppDomains. Use static as the solution
    this (instances) have a high chance of deadlocks
    Use lock over Monitor
    If you must use Monitor, use try...finally
    Inside a lock do as little as possible
    If you are doing math inside the lock rather change to Interlocked
    Never perform long running operations on the UI thread
    Proven Practises II
  • http://www.slideshare.net/rchakra/intro-to-net-threads
    http://www.slideshare.net/psteinb/threading-game-engines-quake-4-enemy-territory-quake-wars
    http://blog.zwares.com/2007/02/net-threads-10-best-practices.html
    http://www.yoda.arachsys.com/csharp/threads/
    http://msdn.microsoft.com/en-us/library/hyz69czz.aspx
    http://msdn.microsoft.com/en-za/magazine/cc300429(en-us).aspx
    http://msdn.microsoft.com/en-us/library/3e8s7xdd(VS.71).aspx
    http://www.albahari.com/threading/
    http://msdn.microsoft.com/en-us/library/ms951089.aspx
    http://www.gotw.ca/publications/concurrency-ddj.htm
    http://brahma.ananthonline.net/
    http://research.microsoft.com/en-us/projects/Accelerator/
    http://stackoverflow.com/questions/1355398/monitor-vs-waithandle-based-thread-sync
    http://www.bluebytesoftware.com/blog/PermaLink,guid,f8404ab3-e3e6-4933-a5bc-b69348deedba.aspx
    http://blogs.msdn.com/brada/archive/2004/05/12/130935.aspx
    http://msdn.microsoft.com/en-us/library/aa645755(VS.71).aspx
    http://msdn.microsoft.com/en-us/magazine/cc164015.aspx
    http://msdn.microsoft.com/en-us/library/ms951089(printer).aspx
    References