Multiple processes can run in parallel on a single computer and multiple threads can run in parallel in a single process.

Similar documents
Programming in.net. Microsoft Development Center Serbia programming course. Lesson 8 Parallelism and Threading in.net

Chapter 13 Working with Threads

Parallelizing Ocean plug-in computations using the Background Worker + PFX pattern

7. MULTITHREDED PROGRAMMING

Advanced Programming C# Lecture 13. dr inż. Małgorzata Janik

CMSC 132: Object-Oriented Programming II. Threads in Java

Advanced Programming C# Lecture 12. dr inż. Małgorzata Janik

Santiago Canyon College Computer Science

Threads are lightweight processes responsible for multitasking within a single application.

The Open Core Interface SDK has to be installed on your development computer. The SDK can be downloaded at:

JAVA and J2EE UNIT - 4 Multithreaded Programming And Event Handling

Threads & Networking

C# Threading. Hans-Wolfgang Loidl School of Mathematical and Computer Sciences, Heriot-Watt University, Edinburgh

Computation Abstractions. Processes vs. Threads. So, What Is a Thread? CMSC 433 Programming Language Technologies and Paradigms Spring 2007

Object Oriented Programming. Week 10 Part 1 Threads

Concurrent Programming

Event-based Asynchronous Pattern Overview 1 Implementing the Event-based Asynchronous Pattern 5 Deciding When to Implement the Event-based

Lecture 8: Threads. Lisa (Ling) Liu

Multithreading and Interactive Programs

Overview. Processes vs. Threads. Computation Abstractions. CMSC 433, Fall Michael Hicks 1

Process Characteristics. Threads Chapter 4. Process Characteristics. Multithreading vs. Single threading

Threads Chapter 4. Reading: 4.1,4.4, 4.5

Multithreaded Programming Part II. CSE 219 Stony Brook University, Department of Computer Science

UNIT IV MULTITHREADING AND GENERIC PROGRAMMING

Threads Chate Patanothai

Java s Implementation of Concurrency, and how to use it in our applications.

Lecture 21: Concurrency in Other Environments (Part 2)

THREADS AND CONCURRENCY

Deadlock. Only one process can use the resource at a time but once it s done it can give it back for use by another process.

Multithreading. Multithreading. HIS CHAPTER DISCUSSES how to write multithreaded code. To do this, Another Thread

Processes and Threads. Industrial Programming. Processes and Threads (cont'd) Processes and Threads (cont'd)

Java Threads. Written by John Bell for CS 342, Spring 2018

CS 160: Interactive Programming

Overview. CMSC 330: Organization of Programming Languages. Concurrency. Multiprocessors. Processes vs. Threads. Computation Abstractions

Multi-threading in Java. Jeff HUANG

Unit 4. Thread class & Runnable Interface. Inter Thread Communication

ASP.NET - MULTI THREADING

Threads. Definitions. Process Creation. Process. Thread Example. Thread. From Volume II

Chapter 3 Process Description and Control

Systems Programming & Scripting

Multitasking Multitasking allows several activities to occur concurrently on the computer. A distinction is usually made between: Process-based multit

SMD149 - Operating Systems

COURSE 11 PROGRAMMING III OOP. JAVA LANGUAGE

Exercise (could be a quiz) Solution. Concurrent Programming. Roadmap. Tevfik Koşar. CSE 421/521 - Operating Systems Fall Lecture - IV Threads

Quiz on Tuesday April 13. CS 361 Concurrent programming Drexel University Fall 2004 Lecture 4. Java facts and questions. Things to try in Java

Animation Part 2: MoveableShape interface & Multithreading

Concurrent Programming

CS 351 Design of Large Programs Threads and Concurrency

Note: Each loop has 5 iterations in the ThreeLoopTest program.

COPYRIGHTED MATERIAL. Contents. Part I: C# Fundamentals 1. Chapter 1: The.NET Framework 3. Chapter 2: Getting Started with Visual Studio

INF 212 ANALYSIS OF PROG. LANGS CONCURRENCY. Instructors: Crista Lopes Copyright Instructors.

Virtual Machine Design

Concurrency & Parallelism. Threads, Concurrency, and Parallelism. Multicore Processors 11/7/17

Chair of Software Engineering. Java and C# in depth. Carlo A. Furia, Marco Piccioni, Bertrand Meyer. Java: concurrency

Threads, Concurrency, and Parallelism

Concurrency - Topics. Introduction Introduction to Subprogram-Level Concurrency Semaphores Monitors Message Passing Java Threads

SUMMARY INTRODUCTION CONCURRENT PROGRAMMING THREAD S BASICS. Introduction Thread basics. Thread states. Sequence diagrams

Advanced Programming Methods. Lecture 6 - Concurrency in Java (1)

CMSC 132: Object-Oriented Programming II

Le L c e t c ur u e e 7 To T p o i p c i s c t o o b e b e co c v o e v r e ed e Multithreading

G Programming Languages Spring 2010 Lecture 13. Robert Grimm, New York University

MultiThreading. Object Orientated Programming in Java. Benjamin Kenwright

CS 556 Distributed Systems

Parallel Programming: Background Information

Parallel Programming: Background Information

JAVA. Lab 12 & 13: Multithreading

Multithreading and Interactive Programs

CMSC 433 Programming Language Technologies and Paradigms. Concurrency

Lecture 2 Process Management

Introduction to Java Threads

MCSA Universal Windows Platform. A Success Guide to Prepare- Programming in C# edusum.com

Call with Current Continuation Patterns

What is a Thread? Individual and separate unit of execution that is part of a process. multiple threads can work together to accomplish a common goal

Lecture 3: Concurrency & Tasking

Programmazione Avanzata e Paradigmi Ingegneria e Scienze Informatiche - UNIBO a.a 2013/2014 Lecturer: Alessandro Ricci

Course Hours

Contribution:javaMultithreading Multithreading Prof. Dr. Ralf Lämmel Universität Koblenz-Landau Software Languages Team

Performance Throughput Utilization of system resources

CS193k, Stanford Handout #8. Threads 3

Process Description and Control. Chapter 3

1. Introduction to Concurrent Programming

Allows program to be incrementally parallelized

Amity School of Engineering

i219 Software Design Methodology 11. Software model checking Kazuhiro Ogata (JAIST) Outline of lecture

Multithread Computing

Multithreading. A thread is a unit of control (stream of instructions) within a process.

CS370 Operating Systems

Microsoft. Microsoft Visual C# Step by Step. John Sharp

Multithreading using Java. Dr. Ferdin Joe John Joseph

Announcements. Program #1. Reading. Due 2/15 at 5:00 pm. Finish scheduling Process Synchronization: Chapter 6 (8 th Ed) or Chapter 7 (6 th Ed)

Chair of Software Engineering. Java and C# in Depth. Prof. Dr. Bertrand Meyer. Exercise Session 8. Nadia Polikarpova

Multithreaded Programming

Program Graph. Lecture 25: Parallelism & Concurrency. Performance. What does it mean?

Threads & Timers. CSE260, Computer Science B: Honors Stony Brook University

Definition Multithreading Models Threading Issues Pthreads (Unix)

BackgroundWorker Component Overview 1 Multithreading with the BackgroundWorker Component 3 Walkthrough Running an Operation in the Background 10 How

Processes. CS 475, Spring 2018 Concurrent & Distributed Systems

Agus Kurniawan Microsoft MVP. Blog

What s An OS? Cyclic Executive. Interrupts. Advantages Simple implementation Low overhead Very predictable

Advanced Concepts of Programming

Transcription:

EE 356 Notes on Threading A process is a program in execution. In an operating system a process has a well-defined state. A five-state model of a process includes: New a process is admitted for high-level scheduling; Ready A process is ready to execute and waiting on processor availability; Running the process is being executed; Waiting the process is suspended waiting on system resources; Halted the process is terminated. A thread is a path of execution within an executable process. It has also been defined as a single sequential flow of control and it is the smallest unit of processing executed by an operating system. Typically a thread has its own separate call stack and its own local variables. Processes are usually independent of one another while threads within a process may be dependent on one another. Processes also typically have separate virtual address spaces whereas threads within a process share an address space. From a programmer's perspective it usually is faster to switch between threads than it is to switch between processes. Multiple processes can run in parallel on a single computer and multiple threads can run in parallel in a single process. A single process can spawn multiple threads which can be executed on multiple CPU cores in parallel. Threading gives the programmer the ability to make use of multi-core machines. Without threading, most processes run on a single core regardless of how many cores are available. Threads are schedule to run by the operating system. There is therefore an advantage to using threads even on machines that have only a single core. On a single core machine, a thread can run in the background leaving a main program responsive to user input from the mouse or keyboard. Without the thread, a computation bound process can appear to freeze up and not respond to user input. The operating system typically uses either preemptive multi-threading or cooperative multithreading to switch between threads. Preemptive multi-threading is also called interleaved multi-threading or fine-grained multithreading. The CPU works with two or more threads simultaneously and switches between them based on the clock cycle or whether or not a given thread is blocked. In general, a thread has little control over when it gets preempted. Cooperative multi-threading also called blocked multi-threading or coarse-grained multithreading. The CPU executes a single thread until the thread is blocked by some event or until the thread itself releases control. In C# (and other languages) threading is an easy way to allow the user to take advantage of multi-core processors and do true parallel execution.

Consider the following example of how threading works: {class Program {static void Main(string[] args) //Must have Using System.Threading Thread t = new Thread (WriteY); // Kick off a new thread t.start(); // running WriteY() // Simultaneously, do something on the main thread. for (i=0;i<500;i++) Console.Write ("x"); static void WriteY() for(i=0;i<500;i++) Console.Write ("y"); /*Prints the following xyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxx yyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyxxxxxxxyyyyyyyxxxxxxxxxxxx xxxxxxxxxxyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyxyxxxxxxxxxxxxxxyyyyyyyy yyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxyyyyy yyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxyyxyxxxxxxxyyyyyyyyyyyyyyxxxxxxxxxxxxxxx xxxxyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyxxxxxyyyyyyyyy yyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxyyyyyyyyyyyyyy yyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxyyyyyyyyyyyyyxxxx xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxyyxxxxxxxxxxxxxyyyy yyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxyyyyyyyyyyy yyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyy yyyyyxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyxxxxyyyyxxxxxxxxxxxxxxxxxxxyyy yyyyyyyyxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyypress any key to continue... */ Figure 1 Two threads printing x and y. We create a new thread named t in the main program which will run the method WriteY. After starting the thread the main program proceeds to print out 500 copies of x. The method WriteY prints 500 copies of y. From the printed output we see that the two threads run at the same time even on a single core machine the two threads will be time sliced to give the appearance of running on two machines. Creating a Thread Threads are created in C# using a delegate called ThreadStart public delegate void ThreadStart(); The thread itself is created when you activate this delegate Thread t = new Thread(new ThreadStart(MyMethod)); To start the thread running you enter t.start(); Note that the user does not create the delegate it is created by the Thread library and the user does not see it. You can shorten the process with the following syntax Thread t = new Thread(MyMethod); t.start();

It is also possible to create a thread that takes a parameter since the constructor is overloaded. The syntax looks like this: Thread t = new Thread(MyMethod); t.start(count);... static void MyMethod(obj MethodObject) {int c = (int) MethodObject; //cast... We can alter the previous example to accept a character parameter like this {class Program {static void Main(string[] args) //Must have Using System.Threading Thread t = new Thread(WriteY); // Kick off a new thread t.start('*'); // running WriteY() // Simultaneously, do something on the main thread. for (i = 0; i < 500; i++) Console.Write("x"); static void WriteY(object obj) for (i = 0; i < 500; i++) Console.Write((char)obj); Figure 2 A thread with a parameter. The parameter passage is limited to a single parameter using this technique. If you need to pass more parameters you use Lambda expressions or the ParameterizedThreadStart delegate. For details on how to use Lambda expressions see Troelson pp. 390-397. The ParameterizedThreadStart method is explained in Troelson pp. 717-719 Thread Names and Other Properties You do not have to name a thread but doing so allows you to track it when you do debugging. Each thread has a Name property which can be set one time. Thread t = new Thread(WriteY); // Kick off a new thread t.name = "MyThread"; t.start('*'); // running WriteY() The following example shows how to obtain other thread properties (from Troelson Fourth Edition pp. 742-743).

{class Program {static void Main(string[] args) {Thread mainthread = Thread.CurrentThread; mainthread.name = "MainThread"; //AppDomain and Context Console.WriteLine("Current AppDomain: {0", Thread.GetDomain().FriendlyName); Console.WriteLine("Current ContextID: {0", Thread.CurrentContext.ContextID); Console.WriteLine("Thread Name: {0", mainthread.name); Console.WriteLine("Has started: {0", mainthread.isalive); Console.WriteLine("Priority level: {0", mainthread.priority); Console.WriteLine("Thread state: {0", mainthread.threadstate); /* Prints the following Current AppDomain: ThreadProperties.exe Current ContextID: 0 Thread Name: MainThread Has started: True Priority level: Normal Thread state: Running Press any key to continue... */ Figure 3 Thread properties. Foreground and Background Confusion It is possible for the user to assign a thread either foreground or background status. This is often confused with the thread's priority but foreground and background status do not imply or convey any priority to the thread. If a thread is in the foreground, the application cannot end until the thread terminates. If a thread is in the background it is considered expendable and an application can terminate even if a background thread is still working. A thread created using Thread.Start() is by default a foreground thread. You can make a thread a background thread like this: Thread back = new Thread(new ThreadStart(MyMethod)); back.isbackground = true; back.start(); For example, suppose you have a thread that is doing nothing but updating the time on the user's screen. This thread could be assigned as a background thread and need not be closed to terminate the application. Thread Priority There are five levels of thread priority: Lowest; BelowNormal; Normal; AboveNormal; and Highest. A thread's priority is meaningful only if you are running multiple threads in one process. Higher priority threads get more execution time than lower priority threads. However, the application in which a process is running also has a priority and the application has to be

running in order for the threads to run. A high priority thread running on a low priority application will not get as much run time as a lower priority thread running on a high priority application. By default, threads are given thread priority "normal". Using the code in Figure 2, you can set the thread priority to highest like this t.priority = ThreadPriority.Highest; t.start('*'); // running WriteY() Running the program using this priority allows the printing of the '*' character to finish first even though the two characters are interlaced. Synchronization Issues When two or more threads run at the same time, the user has only a very coarse control over which thread will finish first and often the threads will not complete in the same order. Since threads can share resources and often have links to other threads by way of the data they operate on, the user must take care that some operations get done in the proper order. The process of doing this is called thread synchronization. There are four mechanisms for doing thread synchronization: Blocking; Locking; Signaling; and Non-blocking synchronization. Blocking To use blocking we force one thread to wait for some period of time or we force it to wait until another thread has completed its task. sleep, and join are typically used in blocking. A method which calls sleep suspends itself for some period of time. Join blocks a calling thread until the specified thread (the one on which join is called) exits. Locking In locking we a thread acquires a lock which effectively prevents other threads from interrupting until the lock is relinquished. The normal way to do this is: private object threadlock = new object(); public void MyMethod() {lock(threadlock) {//everything in this scope cannot be interrupted.... An example of the use of locking is in Troelson pp. 751-754. Signaling For signaling we allow a thread to pause until receiving a notification from another thread. The common signaling device is: Monitor wait/pulse method. These are not discussed in Troelson, but there is a good discussion in C# 4.0 In a Nutshell pp. 840-849. Non-blocking synchronization Non-blocking synchronization makes use of something called memory barriers. Effectively, memory barriers keep two processes from overwriting the same variable or area of memory. See pp. 825-832 in C# 4.0 In a Nutshell. Using Threading

Thread Pool Concept Creating and destroying thread resources can be computationally expensive. In C# a thread pool has been created to reduce this overhead. The idea is that when you need a thread you get it from those available in the pool. This allows the number of threads to be limited and better managed. When you reach the limit of the thread pool, new threads are added in a queue so as not to overburden the CPU. You can access threads from the pool by way of the Background Worker thread, the Task Parallel Library, using delegates, or by the ThreadPool class. For more discussion of the thread pool see Troelson pp. 760-761. Background Worker BackgroundWorker is a helper class that is in the System.ComponentModel namespace. It makes it very easy to use a thread to get asynchronous behavior. The following code illustrates a simple application of a BackgroundWorker. {class Program {//Create a background worker static BackgroundWorker bw = new BackgroundWorker(); static void Main(string[] args) {bw.dowork += DoWorkMethod; //Add method to worker bw.runworkerasync("message to Worker"); Console.WriteLine("Main"); //Create the method that does the work static void DoWorkMethod(object sender, DoWorkEventArgs e) {Console.WriteLine(e.Argument); Console.WriteLine("Done"); Thread.Sleep(5000); Figure 4 Background worker in a console program. The background worker class also provides a way to monitor the progress on the work it is doing, a way to forward errors to the program that started the worker, and a way to easily determine when the work is done. The following example has a GUI. The user enters a number of seconds into the text box. The background worker then counts off the number of quarter seconds and reports progress after each.

{public partial class Form1 : Form {public Form1() {InitializeComponent(); private void btnstart_click(object sender, EventArgs e) {int s = Convert.ToInt32(txt1.Text); pgb1.maximum = 4*s; //maximum value for progress bar bgw1.runworkerasync(s); //Do work asynchronously private void bgw1_dowork(object sender, DoWorkEventArgs e) for(i=0;i<4*(int)e.argument;i++) {Thread.Sleep(250); //update progress bgw1.reportprogress(i); // each quarter second e.result = 4*(int)e.Argument; //Return value when done private void bgw1_progresschanged(object sender, ProgressChangedEventArgs e) {pgb1.value = e.progresspercentage; //Write progress bar private void bgw1_runworkercompleted(object sender, RunWorkerCompletedEventArgs e) {if(e.cancelled) txt1.text = "Cancelled"; else if(e.error!= null) txt1.text = (e.error).tostring(); else txt1.text = "Done"; Figure 5 GUI background worker with progress and termination reported. In a Forms or WFC application the background worker can be dragged as a component into the application. The RunWorkerCompleted, DoWork, and ProgressChanged are events. The Background Worker provides an easy way to use threads to take advantage of a multi-core machine when the application has a few computationally intensive sections that can be isolated to a thread. Task Parallel Library The task parallel library (TPL) is a set of types which will automatically distribute your application across available CPUs using the thread pool in the common language runtime (CLR). As a developer you need not be concerned with how to best partition your application or how to manage your threads. All of the scheduling, partitioning, and thread management is done for you without any intervention. According to Troelson, the TPL is now the recommended way to write parallel applications in.net 4.0.

There are a large number of methods in the parallel class. The two that are used most often are the Parallel.For() and the Parallel.ForEach(). If you are writing code that uses a for or foreach structure to iterate over a large collection of data in an array, ArrayList, a List<T>, or LinQ query, you can substitute the Parallel class versions of these structures and C# will take care of running the loops in parallel. The following example creates three arrays of 10,000,000 random doubles. Each element in the first array is square root of the element in the second array divided by the square root of the element in the third array. The GUI interface has a "Load Data" button which fills the arrays. When it signals that it is done the "Divide" button carries out the operation first as a simple for loop and then as a parallel for loop. The clock ticks for each is printed on labels. {public partial class Form1 : Form {public Form1() {InitializeComponent(); public 8ons tint N = 10000000; private Random r = new Random(); private double [] a1 = new double[n]; private double [] a2 = new double[n]; private double [] a3 = new double[n]; private void Form1_Load(object sender, EventArgs e) {lbldone.text = ""; lbltime1.text = ""; lbltime2.text = ""; private void btnloaddata_click(object sender, EventArgs e) for(i=0;i<n;i++) {a1[i] = ((double)(r.next(1, 1001)))/1000; a2[i] = ((double)(r.next(1, 1001)))/1000; lbldone.text = "Done"; private void btndivide_click(object sender, EventArgs e) {DivideNonParallel(); DivideParallel(); private void DivideNonParallel() long timeticks; timeticks = DateTime.Now.Ticks; for(i=0;i<n;i++) {a3[i] = Math.Sqrt(a1[i])/Math.Sqrt(a2[i]); lbltime1.text = (DateTime.Now.Ticks timeticks).tostring(); private void DivideParallel() {long timeticks; timeticks = DateTime.Now.Ticks; Parallel.For(0, N, i => {a3[i] = Math.Sqrt(a1[i])/Math.Sqrt(a2[i]);); lbltime2.text = (DateTime.Now.Ticks timeticks).tostring(); Figure 6 This program does a math operation on 10,000,000 doubles both as a simple loop and as a parallel loop and compares the required number of clock ticks.

The parallel foreach loop is similar but the parameter list is slightly more complicated. {public Form1() {InitializeComponent(); public const int N = 10000000; private Random r = new Random(); private double [] a1 = new double[n]; private double [] a2 = new double[n]; private double [] a3 = new double[n]; private void Form1_Load(object sender, EventArgs e) {lbldone.text = ""; lbltime1.text = ""; lbltime2.text = ""; private void btnloaddata_click(object sender, EventArgs e) for(i=0;i<n;i++) {a1[i] = ((double)(r.next(1, 1001)))/1000; lbldone.text = "Done"; private void btndivide_click(object sender, EventArgs e) {DivideNonParallel(); DivideParallel(); private void DivideNonParallel() {int i = 0; long timeticks; timeticks = DateTime.Now.Ticks; foreach(double d in a1) {a3[i] = Math.Sqrt(d) + Math.Sqrt(a2[i]); i++; lbltime1.text = (DateTime.Now.Ticks timeticks).tostring(); private void DivideParallel() {long timeticks; timeticks = DateTime.Now.Ticks; Parallel.ForEach(a1, (d, state, i) => {a3[i] = Math.Sqrt(d) + Math.Sqrt(a2[i]); ); lbltime2.text = (DateTime.Now.Ticks timeticks).tostring(); Figure 7 This example illustrates the Parallel.ForEach structure. The Parallel.ForEach syntax is Parallel.ForEach(a1, (d, state, i) => {a3[i] = Math.Sqrt(d) + Math.Sqrt(a2[i]););

It can be read in words as "For each d in a1 do the following calculation: a 3[ i] = d + a2[ i] where i is the index." The variable named state holds the loop state and can be used to force a break in the loop if conditions are met before the loop formally ends. For this simple example the amount of time saved by completing the loop in parallel is not substantial because the parallel loop overhead is close to the time it takes to do the calculation. Also, the numbers shown in the figure are for a dual-core machine. If this same program were to run on a machine with more cores it would be able to automatically scale the threads up to take advantage of the additional resources without further user intervention. The parallel for and foreach are not without their problems. The user must take care how loops get structured especially in cases where data is being written by multiple elements to a common variable. Consider the problem of summing the square roots of the first million digits. A parallel for loop might look like this: Parallel.For(1, 1000000, i => {total += Math.Sqrt(i);); The problem is that every iteration of the loop is writing to total and if more than one iteration is done in parallel it is likely that total will be in error because the value of total will be overwritten while it is being added to by another iteration. The solution is to use a lock on the total variable so that it can be accessed by only one iteration at a time. This, of course, adds immensely to the loop overhead.