Seminar aus
Softwareentwicklung
Threading unter .NET
Daniel Grünberger 9855066
Inhalt
Geschichtlicher Hintergrund
Überblick über Threads
Synchronisation von Daten
AppDomain
Literatur
Inhalt
2
Geschichtlicher Hintergrund
Anfang der Softwareentwicklung verwendeten die
meisten Programme „nur einen“ Prozess
Software-Programme wurden immer komplexer und
umfangreicher– Verwendung von mehreren Prozessen
Probleme:
welcher Prozess bekommt wie viel CPU-Leistung?
Welcher Prozess bekommt welche Ressourcen?
Viel Aufwand für Prozess-Kommunikation und nicht wirklich
effizient
Lösung:
Man erschuf einen leichtgewichtigen Prozess
Entstehung der Threads
Geschichtlicher Hintergrund
3
Überblick über Threads
Was ist ein Thread?
Erstellen eines Threads
Übergabe von Daten an Threads
Überblick über Threads
4
Was ist ein Thread
Ein Thread:
bezeichnet
eine selbständig ausführbare
Programm-Funktion
kann unabhängig vom übrigen Programm
ausgeführt werden
kann so dutzende von Teilaufgaben scheinbar
gleichzeitig ausführen
Was ist ein Thread
5
Verwendung
Falls Programm mehrere Dinge gleichzeitig
machen soll, setzt man Threads ein
Beispiel:
der Zahl PI (3,14159265…) bis auf die
Millionste Stelle genau
Ohne Thread: Programm läuft ein paar Millionen
Jahre ohne Output
Mit Thread: Programm kann jederzeit unterbrochen
werden
Berechnung
Was ist ein Thread
6
Erstellen eines Thread
Klassen/Funktionen für Threads sind im
Namensraum System.Threading zu finden
z.B.:
Start()
Join()
Sleep()
Abort()
...
Erstellen eines Thread
7
Zustandsdiagramm
Erstellen eines Thread
8
Erstellen eines Thread
Beispiel:
using System;
using System.Threading;
Startpunkt: Funktion vom
namespace ThreadHelloWorld
Typ void!
{
class ThreadHelloWorldTest
{
static void ThreadEntry()
Neue Instanz + festlegen
{
des Startpunktes
Console.WriteLine(“Hello Threading World”);
}
static void Main(string[] args)
{
Thread t = new Thread (new ThreadStart(ThreadEntry));
t.Name = “Hello World Thread”;
t.Priority = ThreadPriority.AboveNormal;
t.Start();
t.Join();
Optional: Name des
}
+ Priorität
}
Starten des Thread +
}
Thread
Warten bis beendet
Erstellen eines Thread
9
Übergabe von Daten an Threads
3 Möglichkeiten Daten zu übergeben:
Verwendung
von globalen Variablen
Kapselung des „Entrypoints“ in eine eigene
Klasse
Verwendung von „thread local storage“ (TLS)
Übergabe von Daten an Threads
10
Verwendung von globalen
Variablen
using System;
using System.Threading;
namespace ThreadHelloWorldStaticInformation
{
class ThreadHelloWorldTest
{
static string message;
static void ThreadEntry()
{
Console.WriteLine(message);
}
static void Main(string[] args)
{
message = “Hello World”;
Thread t = new Thread (new ThreadStart(ThreadEntry));
t.Start();
t.Join();
}
}
}
Übergabe von Daten an Threads
Thread gibt Wert der
globalen Variable aus
Wert der globalen Variable
zuweisen
11
Kapselung des „Entrypoints“ in
eigene Klasse
using System;
using System.Threading;
namespace ThreadHelloWorld {
class HelloWorld {
private string message;
public string Message
Daten
{
get{ return message;}
set{ message = value;}
}
public void ThreadEntry()
{
Console.WriteLine(message);
}
}
class DynamicThreadInformation {
static void Main(string[] args)
{
HelloWorld first = new HelloWorld();
first.Message = “Hello World”;
Thread t = new Thread (new
ThreadStart(first.ThreadEntry));
t.Start();
t.Join();
}
}
}
Übergabe von Daten an Threads
Eigene Klasse:
werden einem Property
zugewiesen
Instanz erstellen, Daten zuweisen
und Thread starten
12
Verwendung von „thread local
storage“ (TLS)
using System;
using System.Threading;
namespace ThreadHelloWorld
{
class ThreadLocalStorage
{
static LocalDataStoreSlot slot;
static void ThreadEntry()
{
Console.WriteLine(“The data in the slot is: {0}”,
(string)Thread.GetData(slot));
}
static void Main(string[] args)
{
String message = “Hello World”;
slot = Thread.AllocateDataSlot();
Thread.SetData(slot,message);
Thread t = new Thread (new ThreadStart(ThreadEntry));
t.Start();
t.Join();
}
Daten werden von TLS
ausgelsen
Daten werden in TLS
gestellt
}
}
Übergabe von Daten an Threads
13
Synchronisation von Daten
Relativ einfache Datenübergabe an
Threads
Jedoch Problem bei Multithreading – falls
mehrere Threads auf gleiche Daten /
Ressourcen zugreifen wollen
Synchronisation von Daten
14
Multithreading - Beispiel 1(1/2)
class Worker
{
private int Fib(int x)
{
return ((x<=1)?1:(Fib(x-1)+Fib(x-2)));
}
}
Entrypoint für Thread
public void doWork()
{
string item =
Convert.ToString(Thread.CurrentThread.Name) + “ “;
for (int i =0; i < 10; i++)
{
Console.WriteLine(“Thread {0} {1} {2}”,
item,i,Fib(30));
}
}
Synchronisation von Daten
15
Multithreading - Beispiel 1(2/2)
class UnsynchronizedTest
{
static void Main(string[] args)
{
Worker wq = new Worker();
Thread a = new Thread( new ThreadStart(wq.doWork));
a.Name = “a”;
Thread b = new Thread( new ThreadStart(wq.doWork));
b.Name = “b”;
Thread c = new Thread( new ThreadStart(wq.doWork));
c.Name = “c”;
Thread d = new Thread( new ThreadStart(wq.doWork));
d.Name = “d”;
Thread e = new Thread( new ThreadStart(wq.doWork));
e.Name = “e”;
}
}
a.Start();
b.Start();
c.Start();
d.Start();
e.Start();
Threads werden nicht synchronisiert gestartet
Synchronisation von Daten
16
Ergebnis?
Nicht Zufriedenstellend!!
Synchronisation von Daten
17
Warum?
Jeder Thread versucht CPU-Leistung zu
bekommen
Kein geordnetes vorgehen
Im schlimmsten Fall kann es Threads geben, die
niemals CPU-Leistung bekommen
Synchronisation von Daten
18
Allgemeine
Synchronisationsprobleme
Race-Condition:
zeitlich
unkoordinierte Arbeit zweier Threads
gefährden den erfolgreichen Ablauf eines Programms
Deadlock:
Bei
einem Deadlock warten zwei oder mehrere
Threads aufeinander, und keiner kann sich aus dieser
Situation befreien
Bsp: Dining Philosphers,…
Synchronisation von Daten
19
Race-Condition
public void ThreadProcA(int index)
{
Löschen eines Listenelements
lock(GlobalList)
{
GlobalList.Items.RemoveAt(index);
Es kann vorkommen, dass auf leere
}
}
Listenelemente zugegriffen wird - FEHLER
public void ThreadProcB()
{
For (int x =0; x < GlobalList.Items.Count; x++)
{
//… mehrere zeitaufwändige Operationen
Datenmanipulation: z.B.: Ausgabe
lock(GlobalList)
{
GlobalList.Items[x] = … // irgendeine Manipulation
}
}
}
© 2003 Daniel Grünberger 9855066
20
Deadlock
public void ThreadProcA()
{
lock(RefA)
{
//…
lock(RefB)
{
//…
}
}
}
public void ThreadProcB()
{
lock(RefB)
{
//…
lock(RefA)
{
//…
}
}
}
Resource A wird gesperrt
Wartet vergeblich auf Ressource B
Resource B wird gesperrt
Wartet vergeblich auf Ressource A
Synchronisation von Daten
21
Gegenmaßnahmen
Funktion Monitor bzw. Lock verwenden
Verhindert, dass mehrere Threads
gleichzeitig auf die gleiche Ressource
zugreifen
Man kann Ressourcen für Threads
sperren und wieder freigeben
Synchronisation von Daten
22
Funktion Monitor – Lock
Monitor.Enter(this)
// kritische Ausführung
Monitor.Exit(this);
Bzw.
try
{
Monitor.Enter(this);
// kritische Ausführung}
Finally
{
Monitor.Exit(this)
}
entspricht:
lock(this)
{
//kritische Ausführung
}
Synchronisation von Daten
23
Multithreading - Beispiel 2
public void doWork()
{
Monitor.Enter(this);
string item =
Convert.ToString(Thread.CurrentThread.Name) + “ “;
for (int i =0; i < 10; i++)
{
Console.WriteLine(“Thread {0} {1} {2}”,
item,i,Fib(30));
}
}
Monitor.Exit(this);
Synchronisation von Daten
24
Ergebnis
Liefert das gewünschte Ergebnis
Synchronisation von Daten
25
AppDomain
Was ist ein AppDomain?
Funktionsweise
© 2003 Daniel Grünberger 9855066
26
Was ist ein AppDomain
Ein AppDomains kann als eine Art Prozess
gesehen werden, mit dem kleinen
Unterschied, das dieser weniger
Ressourcen verbraucht
Machen Applikation sicherer und
vielseitiger
Werden auch als „leichtgewichtiger“
Prozess bezeichnet
Was ist ein AppDomain
27
Was ist ein AppDomain
Jede Applikation besitzt einen StandardAppDomain und kommt auch damit aus
Applikation kann aber beliebig viele
AppDomains verwalten
Verwendung:
bei
Verwendung von Bibliotheken die „nicht sicheren
Code“ beinhalten -> in AppDomain kapseln
Plug-Ins im Internet-Explorer
…
Was ist ein AppDomain
28
Was ist ein AppDomain
Was ist ein AppDomain
29
Unterschiede zwischen AppDomain
und einem Thread
AppDomain existiert für die Dauer der
Applikation
ein Thread hingegen existiert nur für eine
bestimmte Zeit innerhalb eines
AppDomains
Was ist ein AppDomain
30
Funktionsweise
AppDomain kann mittels der Methode
CreateDomain() erzeugt werden
Beispiel:
…
AppDomain aDomain = AppDomain.CreateDomain(“My Domain”);
…
ObjectHandle objHandle = aDomain.CreateInstance(
“ProgCSharp”,
// der Assembly Name
“ProgCSharp.Shape”,
// Typ-Name mit Namensraum
False,
// Groß-Kleinschreibung
ign.
System.Reflection.BindingFlags.CreateInstance,
null,
// Binder
new object[] {3,5},
// Argumente
null,
// Culture
null,
// Aktivierungsattribute
null
// Sicherheitsattribure
);
…
Funktionsweise
31
Funktionsweise
using System;
public class MyApp {
public static int main(string[] argv) {
// create Domain
AppDomain child = AppDomain.CreateDomain(“childapp”);
// execute
int r = child.ExecuteAssembly(“yourapp.exe”,null,argv);
//unload domain
AppDomain.Unload(child);
// return result
Return r;
}
}
Funktionsweise
32
Literatur
Don Box, Chris Sells: Essential .NET, The
Common Language Runtime, Addison-Wesley
2003
Kevin Burton: .NET Common Language
Runtime Unleashed, Sams Publishing 2002
Dave Stutz, Ted Neward, Geoff Shilling: Shared
Source CLI Essentials. O’Reilly 2003
Jesse Liberty: Programming C# 2nd Edition,
O’Reilly & Associates Inc. 2002
Literatur
33
ENDE