1 / 40

An Intro to Programming with C# Threads

An Intro to Programming with C# Threads. Presentation by: Jason Bender, Garrett Lund, Ben Gamble, Michael Calvo , and Jeff Corbell. Outline. Introduction The Basics Why use Concurrency The Design of a Thread Facility Using Locks: Accessing Shared Data

chogan
Download Presentation

An Intro to Programming with C# Threads

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. An Intro to Programming with C# Threads Presentation by: Jason Bender, Garrett Lund, Ben Gamble, Michael Calvo, and Jeff Corbell

  2. Outline • Introduction • The Basics • Why use Concurrency • The Design of a Thread Facility • Using Locks: Accessing Shared Data • Using Wait and Pulse: Scheduling Shared Resources • Using Threads: Working in Parallel • Using Interrupt: Diverting the Flow of Control

  3. Threads: The Basics • What is a thread? • Threads allow you to write programs with simultaneous points of execution, synchronizing through shared memory. • Threads are lightweight • Because thread creation, existence, destruction, and synchronization primitives are cheap, programmers will use them for all their concurrency needs.

  4. Single-threaded vs. Multithreaded

  5. Why use concurrency? • Use of multiprocessors • Driving slow devices • Disks, networks, terminals, printers • Human users need concurrency • Distributed systems • Reduce Latency

  6. The Design of a Thread Facility • Four Major Mechanisms • Thread Creation • Mutual Exclusion • Waiting for Events • Getting out of unwanted long-term wait

  7. Thread Creation • In C# you create a thread by: • Creating an object of type “Thread” • Giving its constructor a “ThreadStart” delegate • Calling the thread’s “Start” method • Once Run method is called: 1. Starts executing asynchronously with invocation of delegate's method 2. Method returns 3. Thread dies

  8. Code Example Thread t = new Thread(newThreadStart(foo.A)); t.Start(); foo.B(); t.Join();

  9. Using Locks

  10. Mutual Exclusion • Used to avoid errors with multiple threads accessing shared variables • Using locks is the simplest tool to accomplish this • You must only access data from a thread that is holding that lock

  11. Using Locks (in C#) • General Form: lock(expression) { embedded-statement(s) }

  12. Locking instance fields of an object class KV { string k, v; public void SetKV(string newk, string newv) { lock (this) { this.k = newk; this.v = newv; } } }

  13. Locking Objects by Type static KV head = null; KV next = null; public void AddToList() { lock (typeof(KV)) { this.next = head; head = this; } {

  14. Deadlocks involving only locks • In some systems your program will deadlock if a thread tries to lock a locked object • C# and Java allow an object to be locked multiple times by the same thread • The object remains locked until the object is unlocked the same number of times

  15. Deadlocks involving only locks • Simplest case: thread A locks object M1; thread B locks object M2; thread A blocks trying to lock M2; thread B blocks trying to lock M1. • Simple solution: lock objects in the same order. Make it so all threads do not try to lock M2 until you have obtained the lock to M1

  16. Poor Performance due to locks • The simple solution is not always the best one • If threads A and B operate on separate subsets of the data, locking the whole object would decrease performance

  17. Lock Granularity • Take for example a class that manages a bunch of open buffered files, you should not lock all of the files if you want to write to just one of them • Solution: lock granularity, only lock what you need to • Drawback – Locking becomes more difficult and you might get confused

  18. Using Wait And Pulse

  19. Wait and Pulse • Allows for scheduling multiple threads to share a common resource. • Used when mutual exclusion and locks is not enough • Called from within a lock statement

  20. Example readonly object key = new object(); // thread A lock ( key ) Monitor.Wait( key ); // thread B lock ( key ) Monitor.Pulse( key );

  21. Using “PulseAll” • “PulseAll” awakens all threads that have called “Wait”. • Trades slightly poorer performance for greater simplicity • Two main reasons to use “PulseAll”

  22. Spurious Wake-ups • Awakening threads that cannot make useful progress • Happens when the use of “Wait” is kept simple • Happens when “PulseAll” is used when “Pulse” would have been sufficient • Happens when multiple threads “Wait” on a single object for multiple reasons.

  23. Spurious Lock Conflicts • A thread is awakened from “Waiting” on an object, and before doing useful work the thread blocks trying to lock an object. • C# avoids this problem in simple cases: calling “Monitor.Pulse” which doesn’t actually let the awakened thread start executing. Instead, it is transferred to a “ready queue” on the object.

  24. Starvation • When a program making scheduling decisions does not allow a thread to run. • The thread will never make progress • Ex. Thread A calls “AcquireShared”; i := 1; Thread B calls “AcquireShared”; i := 2; Thread A calls “ReleaseShared”; i := 1; Thread C calls “AcquireShared”; i := 2; Thread B calls “ReleaseShared”; i := 1; … etc.

  25. Deadlocks • Deadlocks can be introduced by waiting on objects, even though you have been careful to have a partial order on acquiring locks. • Ex. Thread A acquires resource (1); Thread B acquires resource (2); Thread A wants (2), so it calls “Monitor.Wait” to wait for (2); Thread B wants (1), so it calls “Monitor.Wait” to wait for (1).

  26. Using Threads

  27. Using Threads: Working in Parallel • Different situations to split a thread • Using a multi-processor • Multitasking • Allowing access to multiple clients

  28. Using Threads in User Interfaces • If a program is processing , UI should respond. • Issues: • Longest delay in the system • Keeping user input relevant

  29. Using Threads in Network Servers • Threads allow a server to assist multiple clients. • Not everyone is on the same page. • RPC-based systems create new threads with every concurrent call. • Other systems only make a new thread for every connection. • Less clutter.

  30. Using Threads in Deferring Work • Users don't want to wait. • Solutions • Simplest: System returns to caller with result to a method. New thread handles remaining work. • Better: Same as before, but a single thread handles remaining work for all processes. • Best: Clean-up thread doesn't need input from any of the main threads. Merges similar requests into the same action.

  31. Using Threads in Pipelining • “Many hands make a burden light.” • Assembly line of data. • Benefit: Makes the most out of multi-processors • Issues: • Balancing equal work amongst all threads. • Knowing how many steps you can use.

  32. Impact of Programming Environs • Some factors to take into account when deciding to use threads. • Capabilities of calling a method: Static vs Instance • Some instance methods require a lock. • Some languages provide a syncronization wrapper around an object instead of needing a lock. • System cost • Significantly more threads than processors results in slowdown due to the stress of constant rescheduling.

  33. Using Interrupt

  34. Interrupts • Definition: • stop a thread and return control to higher level • usually to the level that called the interrupt • Uses: • run competing threads and end after one finishes • an algorithm takes too long and offer user cancel option

  35. Interrupts class PipelinedRasterizer:IDisposable { public void Dispose(){ lock(this){ if(t1 != null) t1.Interrupt(); if(t2 != null) t2.Interrupt(); t1 = null; t2 = null; } } }

  36. Interrupts • calling interrupt requires thread to be in wait, sleep, or join state • in C# have thread call Thread.Sleep(0) occasionally • earlier designs of Java and Modula included easy ways to do this

  37. Interrupts • Cautions • can make code less structured • harder to debug sections of code • Exercise restraint • use interrupts rarely • only use with the abstraction that created the thread

  38. Interrupts • Most useful when you don't really know what's going on • ex. you don't know where a thread could be blocked • Don't confuse with exceptions and abort

  39. Questions?

More Related