1 Lecture 13: Introduction to MultithreadingProf. Aaron LantermanSchool of Electrical and Computer EngineeringGeorgia Institute of Technology2Referencesby Ben Albahari, Peter Drayton, and Brad Merrill, 2001by Joseph Hall, 20083Threading exampleusing System;using System.Threading;class ThreadTest{static void Main() { Thread t = new Thread(new ThreadStart(Go)); t.Start(); Go();} static void Go() { for (char c=‘a’; c <= ‘z’; c++) Console.Write(c); }}static methods are part of theclass, not particular instancesExample from “C# Essentials,” pp. 107-108.4Threading example outputusing Systemusing System.Threading;class ThreadTest{ static void Main() { Thread t = new Thread(new ThreadStart(Go)); t.Start(); Go();} static void Go() { for (char c= ‘a’; c <= ‘z’; c++) Console.Write(c); }}abcdabcdefghijklmnopqrsefghjiklmnopqrstuvwxyztuvwxyzOutput:Example from “C# Essentials,” pp. 107-108.25Lock exampleusing System;using System.Threading;class LockTest {static void Main() { LockTest lt = new LockTest(); Thread t = new Thread(new ThreadStart(lt.Go)); t.Start(); lt.Go();} void Go() { lock(this) for (char c=‘a’; c <= ‘z’; c++) Console.Write(c); }}this references the current instanceof the class (can’t use this in staticmethods)lock takes a reference type; if another thread hasalready acquired a lock, this thread halts until theother thread lets it goExample from“C# Essentials,”p. 1086Locks example outputusing System;using System.Threading;class LockTest {static void Main() { LockTest lt = new LockTest(); Thread t = new Thread(new ThreadStart(lt .Go)); t.Start(); lt.Go();} void Go() { lock(this) for (char c=‘a’; c <= ‘z’; c++) Console.Write(c); }}abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzOutput:Example from“C# Essentials,”p. 1087Pulse and waitusing System;using System.Threading;class MonitorTest { static void Main() { MonitorTest mt = new MonitorTest(); Thread t = new Thread(new ThreadStart(mt.Go)); t.Start(); mt.Go(); } void Go() { for (char c=‘a’; c <= ‘z’; c++) lock(this) { Console.Write(c); Monitor.Pulse(this); Monitor.Wait(this); } }}release lock temporarily; go to sleepuntil another thread pulses mewake up next thread thatis waiting on the objectonce I’ve released itExample from“C# Essentials,”p. 1098Pulse and wait example outputusing System;using System.Threading;class MonitorTest { static void Main() { MonitorTest mt = new MonitorTest(); Thread t = new Thread(new ThreadStart(mt.Go)); t.Start(); mt.Go(); } void Go() { for (char c=‘a’; c <= ‘z’; c++) lock(this) { Console.Write(c); Monitor.Pulse(this); Monitor.Wait(this); } }}aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzzOutput:Example from“C# Essentials,”p. 10839What’s the problem?using System;using System.Threading;class MonitorTest { static void Main() { MonitorTest mt = new MonitorTest(); Thread t = new Thread(new ThreadStart(mt.Go)); t.Start(); mt.Go(); } void Go() { for (char c=‘a’; c <= ‘z’; c++) lock(this) { Console.Write(c); Monitor.Pulse(this); Monitor.Wait(this); } }}release lock temporarily; go to sleepuntil another thread pulses mewake up next thread thatis waiting on the objectonce I’ve released itExample from“C# Essentials,”p. 10910Breaking the deadlock void Go() { for (char c=‘a’; c <= ‘z’; c++) lock(this) { Console.Write(c); Monitor.Pulse(this); if (c < ‘z’) Monitor.Wait(this); } }Example from“C# Essentials,” p. 11011Lock: behind the curtainlock(expression){ //mycode} is syntactic sugar forSystem.Threading.Monitor.Enter(expression);try { // mycode}finally { System.Threading.Monitor.Exit(expression);}From “C# Essentials,” pp. 108-10912Impatient Wait• If another thread doesn’t pulse me withinmillisecondsTimeout, reacquire the lockand wake myself up• Return true if reactivated by monitor beingpulsed• Return false if wait timed outpublic static bool Wait(object obj, int millisecondsTimeout);413Polling• Main thread checks flag variables set bythe worker threads when they finish• Useful if main thread can do some stuff(e.g., eye-candy animation in a turn-basedstrategy game) independently of the workerthreads (e.g. AI), but needs worker threadsto finish before continuing (e.g. making thecomputer’s move)14Polling examplebool done = false;while (!done){Thread.Sleep(0);done = true;for int(i = 0; i < ThreadDone.Length; i++) { done &= m_ThreadDone[i]; }} Code from Joseph Hall, “XNA Game Studio Express,” p. 608Worker thread i sets m_ThreadDone[i]=true before it exits15The problem with polling• Polling takes up “C# cycles”• If your main thread only needs to waituntil its worker threads are done, theWait/Pulse approach is better– Let the .NET runtime handle it!16Locating your threads on the Xbox 360• Set thread affinity within the workerthread immediately after starting it– Don’t forget to call it, or your worker threadwill be running on the same hardwarethread as your main thread• Only available on Xbox 360 XNAThread.CurrentThread.SetProcessorAffinity (new int[] {index});517Check to see if you’re on an Xbox 360#if XBOX360 Thread.CurrentThread.SetProcessorAffinity (new int[] {index});#endif• No way I know of in C# to manually setprocessor affinity in Windows like on theXbox 360• Windows decides what threads run where18Xbox 360 hardware threadsInd CPU Core Comment0 1 1 Not available in XNA1 1 2 Available; main thread; game runs here by default2 2 1 Not available in XNA3 2 2 Available; parts of the Guide and Dashboard live here4 3 1 Available; Xbox Live Marketplace downloads5 3 2 Available; parts of the Guide and Dashboard live here Table from Joseph Hall, “XNA GameStudio Express,” p. 60819Advice Advice from Joseph Hall, “XNA GameStudio Express,” p. 610• More than one thread per core isn’t bad…• …but more than one processor-intensivetask per core is!• Put most intensive tasks on separate cores,and some less-demanding tasks on thosesame cores (threads that work in shortbursts, disk I/O, etc.)20More advice• Limit number of synchronization points• Don’t lock resources longer than necessary• Avoid sharing data when possible• Profile your code before and after to
View Full Document