E N D
Lecture 4 Thread Concepts
Thread Definition A thread is a lightweight process (LWP) which accesses a shared address space provided by by the parent process. Each thread keeps its own state parameters and register values so that it may run concurrently with other threads. Threads may be managed by the OS (kernel-level threads) or by a user application (user-level threads). 2004 Deitel & Associates, Inc.
Threads vs. Processes Processes each have their own address space, text space and resources, while threads spawned within a user application all share the memory and resources of the parentthread or process. A thread defines a single sequential execution stream within a process. Each thread maintains its own PC, SP and CPU register values.
Thread States 2004 Deitel & Associates, Inc.
Thread Operations Threads have some operations in common with processes • Create Exit (terminate) • Suspend Resume • Sleep Wake Other thread operations do not correspond to process operations • Cancel - indicates that a thread should be terminated, but does not guarantee that the thread will be terminated. Threads can mask the cancellation signal. • Join - a primary thread can wait for all other threads to exit by joining them. The joining thread blocks until the thread it joined exits. 2004 Deitel & Associates, Inc.
User-Level Threads A user-level thread is one that is created and managed by a user application. Usually the OS does not know of the existence of user-level threads so additional resources are not provided by the OS for user-level threads. Each user-level thread must share the resources already allocated to the user application. 2004 Deitel & Associates, Inc.
Kernel-Level Threads Kernel-level threads are created and managed by the OS. They attempt to address the limitations of user-level threads by mapping each thread to its own execution context. Kernel-level threads offer increased scalability, interactivity, and throughput, but have a higher overhead due to context switching and reduced portability because of OS-specific APIs 2004 Deitel & Associates, Inc.
Multi-Threading Applications • to utilize a multiprocessor for parallel operations • to do useful work while waiting for a slow device • to satisfy human users by working on several actions at once • to provide network service to multiple clients simultaneously • to defer work until a less busy time • to implement a pipeline process An Introduction to Programming with C# Threads - Andrew D. Birrell
A Simple Multi-Threading Demo using System; using System.Threading; namespace first_thread_demo { publicclassVersion_1 { publicstaticbool done = false; publicstaticvoid T1() { System.Random rnd = newRandom(); while (!done) { Console.WriteLine("T1 in critical section"); Thread.Sleep(rnd.Next(100)); Console.WriteLine("T1 is leaving critical section"); } } staticvoid Main(string[] args) { Thread p = newThread(newThreadStart(T1)); p.Start(); Thread q = newThread(newThreadStart(T2)); q.Start(); Thread.Sleep(5000); done = true; Console.WriteLine("Run Finished"); Console.ReadKey(); } } } publicstaticvoid T2() { System.Random rnd = newRandom(); while (!done) { Console.WriteLine("T2 in critical section"); Thread.Sleep(rnd.Next(100)); Console.WriteLine("T2 is leaving critical section"); } }
BothT1 & T2 can be in Critical Sections at the Same Time T2 is leaving critical section T2 in critical section T1 is leaving critical section T1 in critical section T2 is leaving critical section T2 in critical section T1 is leaving critical section T1 in critical section T1 is leaving critical section T1 in critical section T2 is leaving critical section T2 in critical section T1 is leaving critical section T1 in critical section T2 is leaving critical section T2 in critical section T1 is leaving critical section T1 in critical section T1 is leaving critical section T1 in critical section T2 is leaving critical section T2 in critical section T1 is leaving critical section T1 in critical section T2 is leaving critical section T2 in critical section T1 is leaving critical section T1 in critical section
A "Fix" for the Problem The inclusion of a globally accessible variable threadnumber that can be set to the number of the preferred thread to execute can prevent two threads from entering their critical sections at the same time, but at what cost? public static int threadnumber = 1; : publicstaticvoid T1() { System.Random rnd = newRandom(); while (!done) { while (threadnumber == 2); Console.WriteLine("T1 in critical section"); Thread.Sleep(rnd.Next(100)); Console.WriteLine("T1 is leaving critical section"); threadnumber = 2; } } a very important semicolon
Worker Threads and the BackgroundWorker Class A common application for multithreading is performing time-consuming tasks in the background. The main thread keeps running, while the worker thread does its background job. • A C# application can become multi-threaded in two ways: • (1) by explicitly creating and running additional threads, or • (2) using a feature of the .NET framework that implicitly creates threads • such as BackgroundWorker • thread pooling, • a threading timer • a Remoting server or Web Services • an ASP.NET application. Threading in C#Joseph Albahari
BackgroundWorker Class BackgroundWorker is a helper class in the System.ComponentModel namespace for managing a worker thread. It provides the following features: · A "cancel" flag for signaling a worker to end without using Abort · A standard protocol for reporting progress, completion and cancellation · An implementation of IComponent allowing it be sited in the Visual Studio Designer · Exception handling on the worker thread · The ability to update Windows Forms controls in response to worker progress or completion. The last two features are particularly useful – it means you don't have to include a try/catch block in your worker method, and can update Windows Forms controls without needing to call Control.Invoke. http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx Threading in C#Joseph Albahari
A Simple BackgroundWorker Demo Program 1. Double-click on BackgroundWorker (see link appear below form). 2. Highlight backgroundWorker1 and look at Properties panel. 3. Select events panel (lightning bolt) 4. Double-click on DoWork to create a shell method. 5. Add worker code to this method: Thread.Sleep(1000); This statement will cause the worker to wait 1000 milliseconds (to simulate a time-consuming task). http://dotnetperls.com/backgroundworker
classProgram { publicstaticvoid Main() { Thread[] threads = newThread[10]; Account acc = newAccount(1000); for (int i = 0; i < 10; i++) { Thread t = newThread(newThreadStart(acc.DoTransactions)); threads[i] = t; } for (int i = 0; i < 10; i++) threads[i].Start(); Console.ReadKey(); } } } When Threads Collide Independently executing threads are relatively easy to implement. Issues of complexity and program correctness arise when threads communicate and/or access shared memory. In this example, ten threads are running concurrently, all accessing the same memory space. Open a new "account" acc with 1000 "foobucks". Launch 10 concurrent threads of execution t that make repeated withdrawals from this account ensure that the account is not overdrawn
using System; using System.Threading; using System.Text; namespace lock_demo { classAccount { staticobject locker = newobject(); int balance; Random r = newRandom(); public Account(int initial) { balance = initial; } privateint Withdraw(int amount) { if (balance < 0) thrownewException("Negative Balance"); lock (locker) { 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 } } publicvoid DoTransactions() { for (int i = 0; i < 100; i++) Withdraw(r.Next(1, 100)); } } lock( ) Demo
Results with lock( ) Balance before Withdrawal : 1000 Amount to Withdraw : -87 Balance after Withdrawal : 913 Balance before Withdrawal : 913 Amount to Withdraw : -62 Balance after Withdrawal : 851 Balance before Withdrawal : 851 Amount to Withdraw : -28 Balance after Withdrawal : 823 Balance before Withdrawal : 823 Amount to Withdraw : -3 Balance after Withdrawal : 820 Balance before Withdrawal : 820 Amount to Withdraw : -8 Balance after Withdrawal : 812 Balance before Withdrawal : 812 Amount to Withdraw : -32 Balance after Withdrawal : 780 Balance before Withdrawal : 780 Amount to Withdraw : -16 Balance after Withdrawal : 764 Balance before Withdrawal : 764 Amount to Withdraw : -69 Balance after Withdrawal : 695 Balance before Withdrawal : 695 Amount to Withdraw : -29 Balance after Withdrawal : 666 Balance before Withdrawal : 666 Amount to Withdraw : -42 Balance after Withdrawal : 624 Balance before Withdrawal : 624 Amount to Withdraw : -44 Balance after Withdrawal : 580 Balance before Withdrawal : 580 : : Amount to Withdraw : -22 Balance after Withdrawal : 166 Balance before Withdrawal : 166 Amount to Withdraw : -26 Balance after Withdrawal : 140 Balance before Withdrawal : 140 Amount to Withdraw : -5 Balance after Withdrawal : 135 Balance before Withdrawal : 135 Amount to Withdraw : -57 Balance after Withdrawal : 78 Balance before Withdrawal : 78 Amount to Withdraw : -14 Balance after Withdrawal : 64 Balance before Withdrawal : 64 Amount to Withdraw : -11 Balance after Withdrawal : 53 Balance before Withdrawal : 53 Amount to Withdraw : -16 Balance after Withdrawal : 37 Balance before Withdrawal : 37 Amount to Withdraw : -20 Balance after Withdrawal : 17 Balance before Withdrawal : 17 Amount to Withdraw : -15 Balance after Withdrawal : 2 Balance before Withdrawal : 2 Amount to Withdraw : -1 Balance after Withdrawal : 1 Balance before Withdrawal : 1 Amount to Withdraw : -1 Balance after Withdrawal : 0
Results without lock( ) Balance before Withdrawal : 1000 Amount to Withdraw : -82 Balance after Withdrawal : 918 Balance before Withdrawal : 918 Amount to Withdraw : -33 Balance after Withdrawal : 885 Balance before Withdrawal : 885 Amount to Withdraw : -53 Balance after Withdrawal : 832 Balance before Withdrawal : 832 Amount to Withdraw : -18 Balance after Withdrawal : 814 Balance before Withdrawal : 814 Balance before Withdrawal : 1000 Amount to Withdraw : -94 Balance after Withdrawal : 720 Balance before Withdrawal : 720 Amount to Withdraw : -68 Balance after Withdrawal : 652 Balance before Withdrawal : 652 Amount to Withdraw : -50 Balance after Withdrawal : 602 Balance before Withdrawal : 602 Amount to Withdraw : -16 Balance after Withdrawal : 586 Balance before Withdrawal : 586 Amount to Withdraw : -81 Balance before Withdrawal : 720 Amount to Withdraw : -35 Balance after Withdrawal : 470 Balance before Withdrawal : 470 Amount to Withdraw : -97 Balance after Withdrawal : 373 Amount to Withdraw : -98 Balance after Withdrawal : 275 : : Balance before Withdrawal : 152 Amount to Withdraw : -26 Balance before Withdrawal : 152 Balance before Withdrawal : 275 Balance before Withdrawal : 275 Amount to Withdraw : -3 Balance after Withdrawal : 123 Balance before Withdrawal : 126 Amount to Withdraw : -49 Balance after Withdrawal : 74 Balance before Withdrawal : 126 Amount to Withdraw : -71 Balance after Withdrawal : 3 Amount to Withdraw : -2 Amount to Withdraw : -55 Balance after Withdrawal : 126 Balance after Withdrawal : 1 Balance before Withdrawal : 1 Balance before Withdrawal : 74 Amount to Withdraw : -63 Balance before Withdrawal : 123 Balance before Withdrawal : 74 Balance after Withdrawal : -54 Amount to Withdraw : -59 Balance after Withdrawal : -176 Balance after Withdrawal : -117 Amount to Withdraw : -1 Amount to Withdraw : -71 Balance after Withdrawal : -248 Amount to Withdraw : -54 Balance after Withdrawal : -177 Balance after Withdrawal : -302
Summary A thread is a lightweight process Two or more threads spawned within an application share memory space User-level threads are controlled by the parent process Kernel-level threads are controlled by the OS There are many reasons to build a multithreaded application Multiple threads running independently are easy to implement Effective (and error-free) thread communication and/or interaction is difficult Concurrent (i.e. asynchronous) operation means "order of execution between threads is indeterminate"