lecture 21: concurrency in other environments (part 2) · concurrent programming lecture 21:...
TRANSCRIPT
COMP 150-CCPCOMP 150-CCPConcurrent ProgrammingConcurrent Programming
Lecture 21:Concurrency in Other Environments (Part 2)
Dr. Richard S. Hall [email protected]
Clement [email protected]
Concurrent programming – April 10th, 2008
AgendaAgenda
.NET and C#
What is .NET ?What is .NET ?
“The .NET Framework is Microsoft's managed code programming model for building applications on Windows clients, servers, and mobile or embedded devices.”
“Developers use .NET to build applications of many types: Web applications, server applications, smart client applications, console applications, database applications, and more.”
What is .NET ?What is .NET ?
Win
Common Language Runtime (CLR)
.NET Framework Library
Web Forms, Web Services,
ASP.NETWindows Forms
VB.NET C# J# ManagedC++ Cobol.Net
What is .NET ?What is .NET ?
The CLR is a virtual machine Support several programming languages Interpreting Intermediate Language (MSIL) Close to Java on a lot of points
.NET provides a lot of library to create Windows GUI Web Applications …
Windows Vista uses a lot the .NET framework
Inside the CLRInside the CLR
Class Loader
Garbage Collector
JIT Compiler(IL => Native)
CodeManager
TypeChecker
DebugEngine
ExceptionManager Thread Support COM
Marshaller
Base Class Library
In this LectureIn this Lecture
How to handle multi-threading in C# ? C# is the most famous .NET language Very close to Java
▴ Between C++ and Java
How to create threads How to use monitors How to use condition variables
Using Thread in C#Using Thread in C#
Import the System.Threading namespace using System.Threading; Equivalent to packages in Java
Creating a ThreadCreating a Thread
Two steps: First create a ThreadStart object (delegate)
▴ In argument, give the pointer on the function to callThreadStart ts = new ThreadStart(<function name>);
▴ No Runnable interface to implement
Then, create the Thread objectThread newThread = new Thread(ts);
To Start the Thread, call the start method: newThread.Start();
Thread Creation ExampleThread Creation Example
using System;using System.Threading;class Test { static void Main() { Work w = new Work(); w.Data = 42; ThreadStart threadDelegate = new
ThreadStart(w.DoWork); Thread newThread = new Thread(threadDelegate); newThread.Start(); }}class Work { public int Data; public void DoWork() { Console.WriteLine("Instance thread procedure.
Data={0}", Data); }}
The Simplest Way (with Argument)The Simplest Way (with Argument)
public static void Main() { Thread newThread = new Thread(Work.DoWork);
newThread.Start(42);
Work w = new Work(); newThread = new Thread(w.DoWork);
// Pass an object containing data for the thread. newThread.Start(42);}
public void DoMoreWork(object data) { Console.WriteLine("Instance thread procedure.
Data='{0}'", data); }}
Waiting for Thread TerminationWaiting for Thread Termination
Two Join methods are available on the Thread object
Join() Blocks the calling thread until a thread terminates
Join(Int32) Blocks the calling thread until a thread terminates or
the specified time elapses
Waiting for Thread TerminationWaiting for Thread Termination
An event base system is also available A thread waits until another thread has send an event Several types of event and wait methods are availble.
Waiting for Thread TerminationWaiting for Thread Termination
static void Main() { AutoResetEvent autoEvent = new AutoResetEvent(false); Thread regularThread = new Thread(new ThreadStart(ThreadMethod)); regularThread.Start(); ThreadPool.QueueUserWorkItem(new WaitCallback(WorkMethod),
autoEvent); // Wait for foreground thread to end. regularThread.Join(); // Wait for background thread to end. autoEvent.WaitOne();}static void ThreadMethod() { Console.WriteLine("ThreadOne, executing ThreadMethod, " + "is {0}from the thread pool.", Thread.CurrentThread.IsThreadPoolThread ? "" : "not ");}static void WorkMethod(object stateInfo) { Console.WriteLine("ThreadTwo, executing WorkMethod, " + "is {0}from the thread pool.", Thread.CurrentThread.IsThreadPoolThread ? "" : "not "); // Signal that this thread is finished. ((AutoResetEvent)stateInfo).Set();}
Suspending/Resuming a ThreadSuspending/Resuming a Thread
As in Java, the Suspend and Resume method are obsolete
Using MonitorsUsing Monitors
C# provides a keyword equivalent to the Java synchronized keyword
Lock(object)
This keyword can’t be use on method signature Only in the method code Lock are re-entrant in C#
Using MonitorsUsing Monitors
int Withdraw(int amount) { if (balance < 0) { throw new Exception("Negative Balance"); } lock (this) { if (balance >= amount) { Console.WriteLine("Balance before Withdrawal :
" + balance); Console.WriteLine("Amount to Withdraw :
-" + amount); balance = balance - amount; Console.WriteLine("Balance after Withdrawal :
" + balance); return amount; } else { return 0; // transaction rejected } }}
Using Monitors: The Monitor ClassUsing Monitors: The Monitor Class
Locks are mapped on a static class: the Monitor Class
The lock statement is implemented by using the Enter and Exit methods of the Monitor class, and it uses try…catch…finally to ensure that the lock is released.
A Monitor object maintain A reference to the thread that currently holds the lock. A reference to a ready queue, which contains the
threads that are ready to obtain the lock. A reference to a waiting queue, which contains the
threads that are waiting for notification of a change in the state of the locked object.
Using Monitors: The Monitor ClassUsing Monitors: The Monitor Class
Enter, TryEnter Acquires a lock for an object. This action also marks the
beginning of a critical section. Wait
Releases the lock on an object in order to permit other threads to lock and access the object.
Pulse, PulseAll Sends a signal to one or more waiting threads. The signal
notifies a waiting thread that the state of the locked object has changed, and the owner of the lock is ready to release the lock.
Exit Releases the lock on an object. This action also marks the
end of a critical section protected by the locked object.
Using Monitors: The Monitor ClassUsing Monitors: The Monitor Class
int Withdraw(int amount) { if (balance < 0) { throw new Exception("Negative Balance"); } Monitor.Enter(this); if (balance >= amount) { Console.WriteLine("Balance before Withdrawal :
" + balance); Console.WriteLine("Amount to Withdraw :
-" + amount); balance = balance - amount; Console.WriteLine("Balance after Withdrawal :
" + balance); return amount; } else { return 0; // transaction rejected } Monitor.Exit(this);}
This is not correct !
Using Monitors: The Monitor ClassUsing Monitors: The Monitor Class
int Withdraw(int amount) { if (balance < 0) { throw new Exception("Negative Balance"); } Monitor.Enter(this); if (balance >= amount) { Console.WriteLine("Balance before Withdrawal :
" + balance); Console.WriteLine("Amount to Withdraw :
-" + amount); balance = balance - amount; Console.WriteLine("Balance after Withdrawal :
" + balance); return amount; } else { Monitor.Exit(this); return 0; // transaction rejected } Monitor.Exit(this);}
This is correct !
Monitors & Condition VariablesMonitors & Condition Variables
The Monitor class specify Different wait method
▴ Wait(Object) Releases the lock on an object and blocks the current thread until it
reacquires the lock.▴ Wait(Object, Int32)
Releases the lock on an object and blocks the current thread until it reacquires the lock. If the specified time-out interval elapses, the thread enters the ready queue.
▴ Wait(Object, Int32, Boolean) Releases the lock on an object and blocks the current thread until it
reacquires the lock. If the specified time-out interval elapses, the thread enters the ready queue. This method also specifies whether the synchronization domain for the context (if in a synchronized context) is exited before the wait and reacquired afterward.
Monitors & Condition VariablesMonitors & Condition Variables
The Monitor class specify Different notify method
▴ Pulse Notifies a thread in the waiting queue of a change in the locked
object's state. ▴ PulseAll
Notifies all waiting threads of a change in the object's state.
C# Bounded Buffer C# Bounded Buffer
class LockedBuffer : Buffer { private Object[] buf; private int count = 0; private int input = 0; private int output = 0;
public LockedBuffer(int size) { buf = new Object[size]; }
//…}
C# Bounded Buffer C# Bounded Buffer
public void Put(Object o) { lock (this) { while (count == buf.Length) { try { Monitor.Wait(this); } catch (SynchronizationLockException e) { Console.WriteLine(e); return; } catch (ThreadInterruptedException e) { Console.WriteLine(e); return; } }
Console.WriteLine("PUT "); for (int i = 0; i < count; i++) { Console.WriteLine(" " + buf[(i + output) %
buf.Length] + " "); } Console.WriteLine("[" + o + "]");
buf[input] = o; ++count; input = (input + 1) % buf.Length; Monitor.PulseAll(this); }}
C# Bounded Buffer C# Bounded Buffer
public Object Get() { lock (this) { while (count == 0) { try { Monitor.Wait(this); } catch (SynchronizationLockException e) { Console.WriteLine(e); return null; } catch (ThreadInterruptedException e) { Console.WriteLine(e); return null; } } Object o = buf[output]; buf[output] = null; --count; output = (output + 1) % buf.Length; Monitor.PulseAll(this); Console.WriteLine("GET [" + o + "] "); for (int i = 0; i < count; i++) { Console.WriteLine(buf[(i + output) % buf.Length] + " "); } Console.WriteLine("");
return o; }}
C# Bounded Buffer C# Bounded Buffer
public class Producer { private Buffer buf; private String alphabet = "abcdefghijklmnopqrstuvwxyz"; private bool paused = true;
public Producer(Buffer b) { buf = b; }
public void Pause() { lock (this) { paused = !paused; Monitor.PulseAll(this); } }
public void Run() { int ai = 0; while (true) { lock (this) { while (paused) { Monitor.Wait(this); } } buf.Put((alphabet.ToCharArray()[ai])); ai = (ai + 1) % alphabet.Length; Thread.Sleep(500); } } }}
C# Bounded Buffer C# Bounded Buffer
public class Consumer { private Buffer buf; private bool paused = true;
public Consumer(Buffer b) { buf = b; }
public void Pause() { lock(this) {
paused = !paused;Monitor.PulseAll(this);
} }
public void Run() { while (true) { lock (this) { while (paused) { Monitor.Wait(this); } } Object o = buf.Get(); Thread.Sleep(500); } }}
C# Bounded Buffer C# Bounded Buffer
static void Main(string[] args) {
Buffer buffer = new LockedBuffer(5);
Producer prod = new Producer(buffer);
Consumer cons = new Consumer(buffer);
Thread producer = new Thread(new ThreadStart(prod.Run));
Thread consumer = new Thread(new ThreadStart(cons.Run));
producer.Start();
consumer.Start();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Gui(prod, cons));
}
Other Synchronization MechanismsOther Synchronization Mechanisms
The Managed Thread Pool Timers Wait Handles EventWaitHandle, AutoResetEvent, and
ManualResetEvent Mutexes Interlocked Operations Reader-Writer Locks Semaphores
ConclusionConclusion
.NET provided synchronization mechanisms very similar to Java
It provides almost the same class than the Java Concurrent API
These classes are supported on Compact .NET
All synchronization classes are usable in any others .NET languages
Except the lock macro