View
229
Download
1
Category
Preview:
Citation preview
Windows Programming Using C#
Threading
2
Contents
Threading Thread class Interlocked class Monitor class Semaphore class Thread Pools
3
Threading
A thread is a lightweight process A process runs directly under the operating
system Each process has its own private memory A thread shares memory with other threads Threads run concurrently or pseudo-concurrently
4
Threading
Pseudo-parallelism is simulated by switching the processor rapidly between threads
Threads allow a program to appear to do several things at once
This is vital for many modern programming tasks
5
Threading
.NET supports threading with the System.Threading namespace
This contains classes which allow for the creation and synchronization of concurrent threads
6
Thread Class
The Thread class is the class which creates new threads
The simplest way to create a thread is to pass a parameterless, void method to the constructorThread t = new Thread(doWork);Where doWork() is a void method which does
all of the work of the thread
7
Thread Class
The new thread will start to run once you call t.Start();
The thread will continue to run until The method for the thread exits t.Abort() is called
t.abort() throws a ThreadAbortException which can be caught to perform a cleanup before the thread terminates
8
Thread Class
A thread can be put to sleep for a period This will mark the thread as not runnable
until the period has elapsed t.Sleep(int milliseconds)
Causing a thread to sleep can be used asA primitive timerA way to simulate randomly occurring events
9
Thread Class
Often, you want to block the current thread until one or more other threads complete
This can be used with the join() method t.join();
If you are unsure how long the thread will take, you can specify a timeout t.join(int milliseconds)
This will block until the thread terminates or the timeout elapses
10
Thread Properties
Name A name for the thread which can be set or retrieved
IsAlive True if the thread has started and has not terminated
or aborted
CurrentThread Returns a reference to the currently executing thread
11
Thread Properties
IsBackground Returns true if this is a background thread Can also be set to true or false a thread can be foreground or background Foreground
The process containing foreground threads cannot terminate until all foreground threads have terminated
Background A process can terminate even if background threads in the
process are still alive
12
Shared Data
Threads can perform on their own unless they have to access data shared by another thread
You cannot tell when one thread will stop and another will start
If one thread is halfway through updating shared data and is suspended, another thread will access the half-updated data
This results in data corruption
13
Atomic Operations
In order to prevent data corruption, operations on shared data must be atomic
This means the thread executing the operation cannot be interrupted until the operation is finished
A section of code which cannot be interrupted is called a critical section
14
Interlocked Class
This is a lightweight class which provides atomic operations on simple integers and floating points
All methods of the class are static Methods
int Add(ref int loc, int value) Adds value to loc and returns the new value of loc
15
Interlocked Class
int increment(ref int loc) Adds 1 to the location and returns the new value
int decrement(ref int loc) Subtracts 1 from the location and returns the new
value int CompareExchange(ref int loc, int value, int
comparand) Compares the value in loc to comparand and if equal
assigned value to loc. The original value for loc is returned.
16
Monitor Class
The monitor provides a high-level, easy to use synchronization model
A lock is obtained on an object Once a thread obtains the lock, it has exclusive
access to the object until the lock is released This creates a critical section while a thread
holds the lock on an object
17
Monitor Class
To enter a critical section Monitor.Enter(object);
This obtains a lock on the object No other thread may obtain a lock on this object
while one thread is holding the lock To release the lock
Monitor.Exit(object); This releases the lock at the end of the critical
section
18
Monitor Synchronization
Monitors allow two or more threads to synchronize their operations
This requires that the two threads be able to communicate
The monitor provides three methods for inter-thread communication bool Wait(object) void Pulse(object) void PulseAll(object)
19
Monitor Synchronization
You acquired a lock on the object You test the object state and it is not what you
want You want to release the lock and reacquire it as
soon as the state changes Monitor.Wait(object); Releases the lock Blocks until the lock is reacquired Returns true when the lock is reacquired
20
Monitor Synchronization
Another thread holds the lock and has modified the object so that it is ready for use by another object
It calls Pulse(object); This moves the next thread waiting on the lock to the
ready queue That thread will run after a while and can obtain the
lock
21
Monitor Synchronization
Note:Only the thread which holds the lock can call
Wait()Only the thread which holds the lock can call
Pulse() These restrictions mean that calls to Wait()
and Pulse() must occur within critical sections
22
The Wait/Pulse Advantage
A thread is waiting for an object to change state One way to program this is
Acquire lock
While(object not in desired state) {}
Work on object
Release lock
This is called busy waiting and is VERY inefficient
23
The Wait/Pulse Advantage
The previous code will not work since it never releases the lock to let another thread change the object state
If we provide a method on the object which is synchronized and returns the state, we can make this method better
while(obj.State() != READY) {}Acquire lockDo workRelease lock
24
The Wait/Pulse Advantage
The problem with this solution is that once the right state is obtained, another thread might get the lock before you do
There is also the problem that your look is using CPU time in large amounts
Wait/Pulse provides a solution by blocking the waiting thread until it is unblocked by a call to Pulse
25
Blocking Queue
A blocking queue is a queue which Can add objects to the tail of the queue Can remove objects from the head of the queue
Since both operations modify the queue, they have to synchronized
If the queue is empty, the remove operations should block until data becomes available
The add operation should notify waiting threads that data is ready to be removed from the queue
26
Blocking Queue
Producing Thread
Blocking Queue
Consuming Thread
Wait()
Pulse()
27
Blocking Queue
public class BlockingQueue{
Object[] que; // queue of objectsint queSize; // size of the queueint first, last; // index of first and last members
public BlockingQueue(int maxLen){
que = new object[maxLen];queSize = maxLen;first = 0;last = 0;
}…
}
*see blocking_queue
28
Blocking Queue
public bool add(object o){
Monitor.Enter(this); // acquire lockif((last + 1) == first){
return false;}que[last] = o;last++;if(last >= queSize){
last = 0;}Console.WriteLine("added {0}", o);Monitor.Pulse(this); // notify waiting threads
Monitor.Exit(this); // release lockreturn true;
}
29
Blocking Queue
public object get(){
object result = null;Monitor.Enter(this); // acquire lockif(getSize() == 0){
Monitor.Wait(this); // release lock & wait for notification}result = que[first];first++;if(first >= queSize){
first = 0;}Monitor.Exit(this); // release lockreturn result;
}
30
Testing Blocking Queueclass MainClass{
BlockingQueue que = new BlockingQueue(50);Thread t1, t2;int n = 10;
public MainClass(){
t1 = new Thread(new ThreadStart(writer));t2 = new Thread(new ThreadStart(reader));
t2.Start();t1.Start();
t1.Join();t2.Join();
}…
}
31
Testing Blocking Queue
public void writer(){
for(int i = 0; i < n; i++){
que.add(i.ToString());}
}
public void reader(){
for(int i = 0; i < n; i++){
object o = que.get();Console.WriteLine(o);
}}
32
Semaphore Class
A semaphore is a simple flag which is on or off
Switching a semaphore from one state to another is an atomic operation
A counting semaphore is one with more states and can count up to a maximum value
33
Counting Semaphores
Counting semaphores have the properties A thread requests access to a semaphore If the value is > 0, access is granted and the count is
decremented If the value is 0, the thread is blocked until the count
becomes > 0 When a thread finishes its work, it can release the
semaphore which increments the value and notifies waiting threads
34
Using Semaphores
Semaphores are useful when there is a pool of shared resources
Assume you have 3 tape drives connected to your computer
Multiple threads try to write to a tape Only one thread can write to a tape at once Therefore, a semaphore with a maximum value
of 3 is used to ensure that each thread has access to exactly one tape drive
35
Using Semaphores
We can create a new semaphore by Semaphore pool = new Semaphore(count,
maxCount); Creates a semaphore with maxCount and an initial value of
count
A thread which wants access to a semaphore will call pool.WaitOne(); This will block until the semaphore count is greater
than zero
36
Using Semaphores
After a thread has finished with the resource, it can release the semaphore pool.release(); This increments the count by one and notifies waiting threads
There is also a special form of release which can release more than one unit pool.Release(n); Releases n units Useful for having the main thread make all units available at the
same time *see semaphore_demo
37
Thread Pools
Threads are scarce resourcesYour computer can only create so many of
them Some types of programming have threads
which spend much of their time sleeping or blockedAn example is reading a long message from a
slow internet server
38
Thread Pools
Threads which do little work and sleep most of the time are a waste of resources
Another point is that on many systems it takes time to create a thread and destroy a thread
On these systems it is better to leave the thread sleeping and wake it up only when data arrives for it to handle
39
Thread Pools
A thread pool is a collection of threads which sleep until work arrives
When work arrives, a thread is woken up and dispatched to do the work
When the work is done, the thread goes back to the pool and sleeps until it is needed again
40
ThreadPool Class
The ThreadPool class Implements a thread pool Provides a default of 25 threads per processor Cannot have less than 1 thread per processor Has maximum numbers of threads depending on the
hardware platform There is only one ThreadPool per process All ThreadPool methods are static
41
ThreadPool Class
Methods GetMaxThreads() / Set MaxThreads(n)
Returns or sets the max number of threads in the pool
GetMinThreads() / Set MinThreads(n) Returns or sets the min number of threads in the pool
GetAvailableThreads() Returns the number of threads which are not currently
working
42
ThreadPool Class
QueueUserWorkItem(WaitCallback) Queues some work to be done by the thread pool The work is a method with the signature
void Worker(Object stateInfo); The first available thread is dispatched to execute the
method The thread returns to the pool when the method ends
QueueUserWorkItem(WaitCallback, object) Passes data to stateInfo parameter of worker method
43
ThreadPool Class
All threads in a ThreadPool are background threads
This means that the main thread must wait for the threads in the pool to terminate before the main thread terminates
* see pool_demo
44
Timer Class
The Threading namespace provides a Timer class
This class takes a callback and a period in milliseconds
Each time the period expires, the callback is invoked
To turn a timer off Timer.Dispose();
45
Timer Class
A callback has the signaturevoid TimerHandler(object info);
The info is some data which will be passed by the timer
The callback must be a TimerCallback delegate
46
Timer Class
To create a TimerTimer t = new Timer(
new TimerCallback(TimerHandler),null, // info to pass100, // milliseconds before 1st call5000); // period in milliseconds
*see timer_demo
Recommended