an intro to programming with c# threads

Post on 23-Feb-2016

30 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

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 - PowerPoint PPT Presentation

TRANSCRIPT

An Intro to Programming with C# ThreadsPresentation 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• Using Wait and Pulse: Scheduling Shared Resources• Using Threads: Working in Parallel• Using Interrupt: Diverting the Flow of Control

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.

Single-threaded vs. Multithreaded

Why use concurrency?•Use of multiprocessors•Driving slow devices

▫Disks, networks, terminals, printers•Human users need concurrency•Distributed systems•Reduce Latency

The Design of a Thread Facility•Four Major Mechanisms

1. Thread Creation2. Mutual Exclusion3. Waiting for Events4. Getting out of unwanted long-term wait

Thread Creation•In C# you create a thread by:

1. Creating an object of type “Thread”2. Giving its constructor a “ThreadStart” delegate3. Calling the thread’s “Start” method

•Once Run method is called:1. Starts executing asynchronously with invocation of delegate's method2. Method returns3. Thread dies

Code ExampleThread t = new Thread(new ThreadStart(foo.A)); t.Start();foo.B();t.Join();

Using Locks

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

Using Locks (in C#)•General Form:

lock(expression){ embedded-statement(s) }

Locking instance fields of an objectclass KV {

string k, v; public void SetKV(string newk, string newv) { lock (this)

{ this.k = newk; this.v = newv;

} }

}

Locking Objects by Typestatic KV head = null; KV next = null; public void AddToList() { lock (typeof(KV)) { this.next = head;

head = this; }{

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

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

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

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

Using Wait And Pulse

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

Examplereadonly object key = new object();

// thread A lock ( key ) Monitor.Wait( key );

// thread B lock ( key ) Monitor.Pulse( key );

Using “PulseAll”•“PulseAll” awakens all threads that have

called “Wait”.▫Trades slightly poorer performance for greater

simplicity▫Two main reasons to use “PulseAll”

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.

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.

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.

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).

Using Threads

Using Threads: Working in Parallel Different situations to split a thread

► Using a multi-processor► Multitasking► Allowing access to multiple clients

Using Threads in User Interfaces If a program is processing , UI should

respond.► Issues:

Longest delay in the system Keeping user input relevant

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.

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.

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.

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.

Using Interrupt

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

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

}}

}

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

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

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

Questions?

top related