Threads. Progressing With Parallel Processing(PWPP?) eWeek (09/18/06) Vol. 23, No. 37, P. D5 Multithreading skills are becoming essential as parallel.

Slides:



Advertisements
Similar presentations
Threads. Readings r Silberschatz et al : Chapter 4.
Advertisements

CS162B: POSIX Threads Jacob Chan. Objectives ▪ Review on fork() and exec() – Some issues on forking and exec-ing ▪ POSIX Threads ▪ Lab 8.
Day 10 Threads. Threads and Processes  Process is seen as two entities Unit of resource allocation (process or task) Unit of dispatch or scheduling (thread.
Lecture 4: Concurrency and Threads CS 170 T Yang, 2015 Chapter 4 of AD textbook.
Threads 1 CS502 Spring 2006 Threads CS-502 Spring 2006.
3.5 Interprocess Communication
Lecture 18 Threaded Programming CPE 401 / 601 Computer Network Systems slides are modified from Dave Hollinger.
Unix Threads operating systems. User Thread Packages pthread package mach c-threads Sun Solaris3 UI threads Kernel Threads Windows NT, XP operating systems.
1 Threads Chapter 4 Reading: 4.1,4.4, Process Characteristics l Unit of resource ownership - process is allocated: n a virtual address space to.
Thread. A basic unit of CPU utilization. It comprises a thread ID, a program counter, a register set, and a stack. It is a single sequential flow of control.
Operating Systems Chapter 5 Threads. Benefits Responsiveness Resource Sharing Economy Utilization of MP Architectures.
Chapter 4: Threads. 4.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts Threads A thread (or lightweight process) is a basic unit of CPU.
PRINCIPLES OF OPERATING SYSTEMS Lecture 6: Processes CPSC 457, Spring 2015 May 21, 2015 M. Reza Zakerinasab Department of Computer Science, University.
10/16/ Realizing Concurrency using the thread model B. Ramamurthy.
© 2004, D. J. Foreman 2-1 Concurrency, Processes and Threads.
Lecture 3 Process Concepts. What is a Process? A process is the dynamic execution context of an executing program. Several processes may run concurrently,
 2004 Deitel & Associates, Inc. All rights reserved. 1 Chapter 4 – Thread Concepts Outline 4.1 Introduction 4.2Definition of Thread 4.3Motivation for.
B. RAMAMURTHY 10/24/ Realizing Concurrency using the thread model.
CS 346 – Chapter 4 Threads –How they differ from processes –Definition, purpose Threads of the same process share: code, data, open files –Types –Support.
1 Threads Chapter 11 from the book: Inter-process Communications in Linux: The Nooks & Crannies by John Shapley Gray Publisher: Prentice Hall Pub Date:
Copyright ©: University of Illinois CS 241 Staff1 Threads Systems Concepts.
Source: Operating System Concepts by Silberschatz, Galvin and Gagne.
CS333 Intro to Operating Systems Jonathan Walpole.
1 Pthread Programming CIS450 Winter 2003 Professor Jinhua Guo.
Pthreads.
Silberschatz, Galvin and Gagne  2002 Modified for CSCI 399, Royden, Operating System Concepts Operating Systems Lecture 14 Threads 2 Read Ch.
Silberschatz, Galvin and Gagne ©2005 Modified by Dimitris Margaritis, Spring 2007 Chapter 4: Threads.
12/22/ Thread Model for Realizing Concurrency B. Ramamurthy.
© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Operating Systems Processes and Threads.
CSC 322 Operating Systems Concepts Lecture - 7: by Ahmed Mumtaz Mustehsan Special Thanks To: Tanenbaum, Modern Operating Systems 3 e, (c) 2008 Prentice-Hall,
Copyright ©: Nahrstedt, Angrave, Abdelzaher
Threads A thread is an alternative model of program execution
CSS430 Threads1 Textbook Ch5 These slides were compiled from the OSC textbook slides (Silberschatz, Galvin, and Gagne) and the instructor’s class materials.
2.2 Threads  Process: address space + code execution  There is no law that states that a process cannot have more than one “line” of execution.  Threads:
B. RAMAMURTHY 5/10/2013 Amrita-UB-MSES Realizing Concurrency using the thread model.
7/9/ Realizing Concurrency using Posix Threads (pthreads) B. Ramamurthy.
CMSC 421 Spring 2004 Section 0202 Part II: Process Management Chapter 5 Threads.
Tutorial 4. In this tutorial session we’ll see Threads.
Chapter 4 – Thread Concepts
Realizing Concurrency using the thread model
Threads Some of these slides were originally made by Dr. Roger deBry. They include text, figures, and information from this class’s textbook, Operating.
CS 6560: Operating Systems Design
Realizing Concurrency using the thread model
Day 12 Threads.
Chapter 4 – Thread Concepts
CS399 New Beginnings Jonathan Walpole.
Thread Programming.
Threads.
Chapter 2 Processes and Threads Today 2.1 Processes 2.2 Threads
Chapter 4: Threads.
Realizing Concurrency using Posix Threads (pthreads)
Operating Systems Lecture 13.
Realizing Concurrency using the thread model
Thread Programming.
Realizing Concurrency using the thread model
Threads Chapter 4.
Operating System Concepts
Threads Chapter 5 2/17/2019 B.Ramamurthy.
Jonathan Walpole Computer Science Portland State University
Threads Chapter 5 2/23/2019 B.Ramamurthy.
Realizing Concurrency using the thread model
Realizing Concurrency using Posix Threads (pthreads)
Still Chapter 2 (Based on Silberchatz’s text and Nachos Roadmap.)
Realizing Concurrency using the thread model
Realizing Concurrency using Posix Threads (pthreads)
CS510 Operating System Foundations
Foundations and Definitions
Outline Chapter 3: Processes Chapter 4: Threads So far - Next -
Concurrency, Processes and Threads
Presentation transcript:

Threads

Progressing With Parallel Processing(PWPP?) eWeek (09/18/06) Vol. 23, No. 37, P. D5 Multithreading skills are becoming essential as parallel processing hardware proliferates, and developers ignore at their own peril indications of this trend such as Intel's investments in college curriculum and resources for multithread development training. The Java programming language supports the expression of concurrency in the same language developers are already employing for application logic, while powerful abstractions for C++ are also offered by concurrency toolkits and frameworks. Being able to count the threads developers are using on the fingers of one hand is folly, according to principal author of "Java Concurrency in Practice" Brian Goetz. He and his five co-authors note that "The need for thread safety is contagious," because "frameworks may create threads on your behalf, and code called from these threads must be thread-safe.“ It is the authors' contention that developers should never lose sight of the application state and avoid becoming overwhelmed by threading mechanisms. Developers must also keep in mind that careless habits that are acceptable in single- thread environments may be exposed in multithread environments.

2.2 Threads  Process: address space + code execution  There is no law that states that a process cannot have more than one “line” of execution.  Threads: single address space + many threads of execution

2.2 Threads  Process: address space + code execution  separate global variables  separate stack (and stack address space)  separate open files  separate signals  separate child processes, …

2.2 Threads  Process: address space + code execution  separate global variables  separate stack (and stack address space)  separate open files  separate signals  separate child processes, …  Threads: single address space + many threads of execution  shared global variables  shared stack address space (but separate stacks)  shared open files  shared signals  shared child processes,,,,

Threads  Process – used to group resources together; has at least one thread  Thread – actual entity scheduled for execution on CPU  Threads are sometimes called lightweight processes (LWPs)  Multithreading – multiple threads in the same process

32

Thread functions  Create threads: #include #include int pthread_create ( pthread_t* thread, pthread_attr_t* attr, void* (*start_routine)(void*), void* arg );

Thread functions  Create threads: #include #include int pthread_create ( pthread_t* thread, pthread_attr_t* attr, void* (*start_routine)(void*), void* arg ); This parameter, start_routine, is the address of a function (*start_routine). This function has one argument, a “generic” pointer (void*). This function returns a “generic” pointer (void*). (We will see an example shortly.)

Thread termination void pthread_exit ( void* retval ); int pthread_cancel ( pthread_t thread );

Types of processes (or threads) 1. compute bound 2. I/O bounds 3. mixed

Why threads?  easier to create a thread than a process  share resources  computation and I/O within a single process on a single processor can be overlapped  computation (and computation in other threads) within a single process on a multiprocessor can be overlapped

Example: word processor  Multiple threads: 1.User interaction 2.Document reformatting 3.Automatic saving/backups  Alternative is everything else stops when (2) or (3) occurs.

Example: web server  dispatcher thread – handles incoming requests  worker threads – performs request 1.Checks cache 2.Reads from disk if necessary 3.Adds to cache

Threads and alternatives 1. Threads retain the simple sequential, blocking model while allowing for parallelism.  May be in user space or kernel. 2. (alternative) The single threaded server retains the simple sequential, block model but performance suffers (no parallelism). 3. (alternative) Finite state machine = each computation has a saved state and there exists some set of events that can occur to change the state.  high performance through parallelism  uses nonblocking calls and interrupts (not simple)

Threads Thread types: 1.detached  relatively independent 2.joinable  waiting for completion 3.popup threads  like signal handlers that have their own threads

Threads Implementations: 1.user space  scheduling is the responsibility of the user 2.kernel  threads are scheduled by the OS (like processes) 3.hybrid  win32 supports both threads (kernel), and fibers (user space)

Pitfall: global variables #include #include bool err = false; void* t1 ( void* p ) { … err = true; if (err) puts( "hello" ); //may never get here! …} void* t2 ( void* p ) { … err = false; …} int main ( int argc, char* argv[] ) { … if (err) puts( "something bad happened." ); …} global variable (shared by all threads)

Pitfall: global variables #include #include bool err = false; void* t1 ( void* p ) { … ::err = true; if (::err) puts( "hello" ); //may never get here! …} void* t2 ( void* p ) { … ::err = false; …} int main ( int argc, char* argv[] ) { … if (::err) puts( "something bad happened." ); …} Interesting note: C++ scope resolution operator may be used to indicate global variable.

Pitfall: global variables #include #include bool err = false; void* t1 ( void* p ) { … err = true; if (err) puts( "hello" ); //may never get here! …} void* t2 ( void* p ) { … err = false; …} int main ( int argc, char* argv[] ) { … if (err) puts( "something bad happened." ); …} The main thread creates two additional threads, t1 and t2. Pointers indicate next line to be executed by thread.

Pitfall: global variables #include #include bool err = false; void* t1 ( void* p ) { … err = true; if (err) puts( "hello" ); //may never get here! …} void* t2 ( void* p ) { … err = false; …} int main ( int argc, char* argv[] ) { … if (err) puts( "something bad happened." ); …} Say t1 executes this line.

Pitfall: global variables #include #include bool err = false; void* t1 ( void* p ) { … err = true; if (err) puts( "hello" ); //may never get here! …} void* t2 ( void* p ) { … err = false; …} int main ( int argc, char* argv[] ) { … if (err) puts( "something bad happened." ); …} But it gets interrupted. Now it’s t2’s turn.

Pitfall: global variables #include #include bool err = false; void* t1 ( void* p ) { … err = true; if (err) puts( "hello" ); //may never get here! …} void* t2 ( void* p ) { … err = false; …} int main ( int argc, char* argv[] ) { … if (err) puts( "something bad happened." ); …} So t2 executes. Now it’s t1’s turn.

Pitfall: global variables #include #include bool err = false; void* t1 ( void* p ) { … err = true; if (err) puts( "hello" ); //may never get here! …} void* t2 ( void* p ) { … err = false; …} int main ( int argc, char* argv[] ) { … if (err) puts( "something bad happened." ); …} t1 doesn’t print “hello.” Why not? It set err to true on the previous line! Note: We get a different result if t2 went first!

Pitfalls: global variables

Pitfall: global variables Possible solutions: 1.Don’t use ‘em. 2.Create thread-wide globals (using your own libraries). 3.Other mechanisms (that we will explore in the future).

Other pitfalls  Libraries may not be reentrant  Solution: rewrite the library  Solution: wrap each library call with a wrapper  Signals, alarms, and I/O may not be thread specific.

Other pthread functions  int thread_yield ( );  int pthread_join ( pthread_t th, void** thread_return );  Many, many others

Multithreaded example

/* file:pt1.cpp file:pt1.cpp date:23-sep-2005 date:23-sep-2005 author:george j. grevera, ph.d. author:george j. grevera, ph.d. compile:g++ -o pt1.exe pt1.cpp -lpthread -lm compile:g++ -o pt1.exe pt1.cpp -lpthread -lm desc.:shell of a multithreaded app desc.:shell of a multithreaded app*/ #include #include //global variables const intN = 10;//max number of threads pthread_tthread[ N ];//for thread id storage // Additional system libraries that are needed.

// //program execution begins here. int main ( int argc, char* argv[] ) { //create N threads //create N threads for (int i=0; i<N; i++) { for (int i=0; i<N; i++) { pthread_create( &thread[i], 0, start_routine, (void*)i ); pthread_create( &thread[i], 0, start_routine, (void*)i ); printf( "main: thread %d created. \n", thread[i] ); printf( "main: thread %d created. \n", thread[i] ); } //wait for the N threads to finish //wait for the N threads to finish for (int i=0; i<N; i++) { for (int i=0; i<N; i++) { void* v; void* v; printf( "main: waiting \n" ); printf( "main: waiting \n" ); pthread_join( thread[i], &v ); pthread_join( thread[i], &v ); } printf( "main: returning \n" ); printf( "main: returning \n" ); return 0; return 0;}//

// //example worker thread function. //this function does a lot of “work” (i.e., computation). double doWork ( const int whoAmI ) { double sum = 0.0; double sum = 0.0; for (int i=0; i< ; i++) { for (int i=0; i< ; i++) { sum += sin( i ) * cos( i ); sum += sin( i ) * cos( i ); } return sum; return sum;}// //main thread function void* start_routine ( void* p ) { int whoAmI = (int)p; int whoAmI = (int)p; printf( "%d processing \n", whoAmI ); printf( "%d processing \n", whoAmI ); doWork( whoAmI ); doWork( whoAmI ); printf( "%d exit \n", whoAmI ); printf( "%d exit \n", whoAmI ); return 0; return 0;}//

/* file: pt1.cpp date: 23-sep-2005 author: george j. grevera, ph.d. compile: g++ -o pt1.exe pt1.cpp -lpthread -lm desc.: shell of a multithreaded app */ #include #include //global variables const int N = 10; //max number of threads pthread_t thread[N]; //for thread id storage // //example worker thread function. this function does a lot of "work" // (i.e., computation). double doWork ( const int whoAmI ) { double sum = 0.0; double sum = 0.0; for (int i=0; i< ; i++) { for (int i=0; i< ; i++) { sum += sin( i ) * cos( i ); sum += sin( i ) * cos( i ); } return sum; return sum;}// //main thread function void* start_routine ( void* p ) { int whoAmI = (int)p; int whoAmI = (int)p; printf( "%d processing \n", whoAmI ); printf( "%d processing \n", whoAmI ); doWork( whoAmI ); doWork( whoAmI ); printf( "%d exit \n", whoAmI ); printf( "%d exit \n", whoAmI ); return 0; return 0;}// //program execution begins here. int main ( const int argc, const char* const argv[] ) { //create N threads //create N threads for (int i=0; i<N; i++) { for (int i=0; i<N; i++) { pthread_create( &thread[i], 0, start_routine, (void*)i ); pthread_create( &thread[i], 0, start_routine, (void*)i ); printf( "main: thread %d created. \n", thread[i] ); printf( "main: thread %d created. \n", thread[i] ); } //wait for the N threads to finish //wait for the N threads to finish for (int i=0; i<N; i++) { for (int i=0; i<N; i++) { void* v; void* v; printf( "main: waiting \n" ); printf( "main: waiting \n" ); pthread_join( thread[i], &v ); pthread_join( thread[i], &v ); } printf( "main: returning \n" ); printf( "main: returning \n" ); return 0; return 0;}// complete example

Multithreading discussion  pthread_create only allows a single parameter to be passed to the thread  pthread_join only allows a single parameter to be returned from a thread  How can we pass and return many parameters?

MULTITHREADING: ADVANCED TOPIC

Multithreading: advanced topic  We know that process memory is shared among all threads.  We know that the stack is part of the process memory.  Therefore the stack is part of the memory that is shared among the threads.  How can we demonstrate that the stack is shared among threads?

/* This program demonstrates that, although stack variables are not shared among threads, stack memory (_all_ process memory) is indeed shared by threads. g++ -o sharedStack.exe sharedStack.cpp -lpthread -lm -lrt */ #include #include using namespace std; const int N = 2; //max number of threads //this will be a pointer to a local variable in thread 0. static int* whoAmIPointer = NULL; // From where are local variables allocated?

// int main ( const int argc, const char* const argv[] ) { pthread_t thread[::N]; //for thread id storage pthread_t thread[::N]; //for thread id storage //create N threads //create N threads for (int i=0; i< ::N; i++) { for (int i=0; i< ::N; i++) { pthread_create( &thread[i], 0, start_routine, (void*)i ); pthread_create( &thread[i], 0, start_routine, (void*)i ); cout << "main: thread " << i << " created with id=" << thread[i] cout << "main: thread " << i << " created with id=" << thread[i] << endl; << endl; } //wait for the N threads to finish //wait for the N threads to finish for (int i=0; i< ::N; i++) { for (int i=0; i< ::N; i++) { void* v; void* v; cout << "main: wait" << endl; cout << "main: wait" << endl; pthread_join( thread[i], &v ); pthread_join( thread[i], &v ); } cout << "main: returning" << endl; cout << "main: returning" << endl; return 0; return 0;}// Nothing new here.

// void* start_routine ( void* p ) { int whoAmI = (int)p; int whoAmI = (int)p; int whoAmICopy = whoAmI; int whoAmICopy = whoAmI; cout << whoAmI << " processing" << endl; cout << whoAmI << " processing" << endl; if (whoAmI==0) { //is this thread 0? if (whoAmI==0) { //is this thread 0? //make the global var point to my local var //make the global var point to my local var ::whoAmIPointer = &whoAmI; ::whoAmIPointer = &whoAmI; sched_yield(); sched_yield(); sleep( 5 ); sleep( 5 ); } else { } else { //this is not thread 0 so wait until thread 0 sets the global var //this is not thread 0 so wait until thread 0 sets the global var // that points to thread 0's local var. // that points to thread 0's local var. while (::whoAmIPointer==NULL) { while (::whoAmIPointer==NULL) { sched_yield(); sched_yield(); } //change thread 0's local var //change thread 0's local var *::whoAmIPointer = 92; *::whoAmIPointer = 92; } if (whoAmI!=whoAmICopy) { if (whoAmI!=whoAmICopy) { cout << "Hey! Wait a minute! Somebody changed who I am from " cout << "Hey! Wait a minute! Somebody changed who I am from " << whoAmICopy << " to " << whoAmI << "!" << endl; << whoAmICopy << " to " << whoAmI << "!" << endl; } cout << whoAmI << " done" << endl cout << whoAmI << " done" << endl << whoAmI << " exit" << endl; << whoAmI << " exit" << endl; return 0; return 0;}// What does :: mean in C++?

// void* start_routine ( void* p ) { int whoAmI = (int)p; int whoAmI = (int)p; int whoAmICopy = whoAmI; int whoAmICopy = whoAmI; cout << whoAmI << " processing" << endl; cout << whoAmI << " processing" << endl; if (whoAmI==0) { //is this thread 0? if (whoAmI==0) { //is this thread 0? //make the global var point to my local var //make the global var point to my local var ::whoAmIPointer = &whoAmI; ::whoAmIPointer = &whoAmI; sched_yield(); sched_yield(); sleep( 5 ); sleep( 5 ); } else { } else { //this is not thread 0 so wait until thread 0 sets the global var //this is not thread 0 so wait until thread 0 sets the global var // that points to thread 0's local var. // that points to thread 0's local var. while (::whoAmIPointer==NULL) { while (::whoAmIPointer==NULL) { sched_yield(); sched_yield(); } //change thread 0's local var //change thread 0's local var *::whoAmIPointer = 92; *::whoAmIPointer = 92; } if (whoAmI!=whoAmICopy) { if (whoAmI!=whoAmICopy) { cout << "Hey! Wait a minute! Somebody changed who I am from " cout << "Hey! Wait a minute! Somebody changed who I am from " << whoAmICopy << " to " << whoAmI << "!" << endl; << whoAmICopy << " to " << whoAmI << "!" << endl; } cout << whoAmI << " done" << endl cout << whoAmI << " done" << endl << whoAmI << " exit" << endl; << whoAmI << " exit" << endl; return 0; return 0;}// What does :: mean in C++? :: is the C++ scope resolution operator. In this case, it refers to a global variable.

// void* start_routine ( void* p ) { int whoAmI = (int)p; int whoAmI = (int)p; int whoAmICopy = whoAmI; int whoAmICopy = whoAmI; cout << whoAmI << " processing" << endl; cout << whoAmI << " processing" << endl; if (whoAmI==0) { //is this thread 0? if (whoAmI==0) { //is this thread 0? //make the global var point to my local var //make the global var point to my local var ::whoAmIPointer = &whoAmI; ::whoAmIPointer = &whoAmI; sched_yield(); sched_yield(); sleep( 5 ); sleep( 5 ); } else { } else { //this is not thread 0 so wait until thread 0 sets the global var //this is not thread 0 so wait until thread 0 sets the global var // that points to thread 0's local var. // that points to thread 0's local var. while (::whoAmIPointer==NULL) { while (::whoAmIPointer==NULL) { sched_yield(); sched_yield(); } //change thread 0's local var //change thread 0's local var *::whoAmIPointer = 92; *::whoAmIPointer = 92; } if (whoAmI!=whoAmICopy) { if (whoAmI!=whoAmICopy) { cout << "Hey! Wait a minute! Somebody changed who I am from " cout << "Hey! Wait a minute! Somebody changed who I am from " << whoAmICopy << " to " << whoAmI << "!" << endl; << whoAmICopy << " to " << whoAmI << "!" << endl; } cout << whoAmI << " done" << endl cout << whoAmI << " done" << endl << whoAmI << " exit" << endl; << whoAmI << " exit" << endl; return 0; return 0;}//

// void* start_routine ( void* p ) { int whoAmI = (int)p; int whoAmI = (int)p; int whoAmICopy = whoAmI; int whoAmICopy = whoAmI; cout << whoAmI << " processing" << endl; cout << whoAmI << " processing" << endl; if (whoAmI==0) { //is this thread 0? if (whoAmI==0) { //is this thread 0? //make the global var point to my local var //make the global var point to my local var ::whoAmIPointer = &whoAmI; ::whoAmIPointer = &whoAmI; sched_yield(); sched_yield(); sleep( 5 ); sleep( 5 ); } else { } else { //this is not thread 0 so wait until thread 0 sets the global var //this is not thread 0 so wait until thread 0 sets the global var // that points to thread 0's local var. // that points to thread 0's local var. while (::whoAmIPointer==NULL) { while (::whoAmIPointer==NULL) { sched_yield(); sched_yield(); } //change thread 0's local var //change thread 0's local var *::whoAmIPointer = 92; *::whoAmIPointer = 92; } if (whoAmI!=whoAmICopy) { if (whoAmI!=whoAmICopy) { cout << "Hey! Wait a minute! Somebody changed who I am from " cout << "Hey! Wait a minute! Somebody changed who I am from " << whoAmICopy << " to " << whoAmI << "!" << endl; << whoAmICopy << " to " << whoAmI << "!" << endl; } cout << whoAmI << " done" << endl cout << whoAmI << " done" << endl << whoAmI << " exit" << endl; << whoAmI << " exit" << endl; return 0; return 0;}//

// void* start_routine ( void* p ) { int whoAmI = (int)p; int whoAmI = (int)p; int whoAmICopy = whoAmI; int whoAmICopy = whoAmI; cout << whoAmI << " processing" << endl; cout << whoAmI << " processing" << endl; if (whoAmI==0) { //is this thread 0? if (whoAmI==0) { //is this thread 0? //make the global var point to my local var //make the global var point to my local var ::whoAmIPointer = &whoAmI; ::whoAmIPointer = &whoAmI; sched_yield(); sched_yield(); sleep( 5 ); sleep( 5 ); } else { } else { //this is not thread 0 so wait until thread 0 sets the global var //this is not thread 0 so wait until thread 0 sets the global var // that points to thread 0's local var. // that points to thread 0's local var. while (::whoAmIPointer==NULL) { while (::whoAmIPointer==NULL) { sched_yield(); sched_yield(); } //change thread 0's local var //change thread 0's local var *::whoAmIPointer = 92; *::whoAmIPointer = 92; } if (whoAmI!=whoAmICopy) { if (whoAmI!=whoAmICopy) { cout << "Hey! Wait a minute! Somebody changed who I am from " cout << "Hey! Wait a minute! Somebody changed who I am from " << whoAmICopy << " to " << whoAmI << "!" << endl; << whoAmICopy << " to " << whoAmI << "!" << endl; } cout << whoAmI << " done" << endl cout << whoAmI << " done" << endl << whoAmI << " exit" << endl; << whoAmI << " exit" << endl; return 0; return 0;}//

// void* start_routine ( void* p ) { int whoAmI = (int)p; int whoAmI = (int)p; int whoAmICopy = whoAmI; int whoAmICopy = whoAmI; cout << whoAmI << " processing" << endl; cout << whoAmI << " processing" << endl; if (whoAmI==0) { //is this thread 0? if (whoAmI==0) { //is this thread 0? //make the global var point to my local var //make the global var point to my local var ::whoAmIPointer = &whoAmI; ::whoAmIPointer = &whoAmI; sched_yield(); sched_yield(); sleep( 5 ); sleep( 5 ); } else { } else { //this is not thread 0 so wait until thread 0 sets the global var //this is not thread 0 so wait until thread 0 sets the global var // that points to thread 0's local var. // that points to thread 0's local var. while (::whoAmIPointer==NULL) { while (::whoAmIPointer==NULL) { sched_yield(); sched_yield(); } //change thread 0's local var //change thread 0's local var *::whoAmIPointer = 92; *::whoAmIPointer = 92; } if (whoAmI!=whoAmICopy) { if (whoAmI!=whoAmICopy) { cout << "Hey! Wait a minute! Somebody changed who I am from " cout << "Hey! Wait a minute! Somebody changed who I am from " << whoAmICopy << " to " << whoAmI << "!" << endl; << whoAmICopy << " to " << whoAmI << "!" << endl; } cout << whoAmI << " done" << endl cout << whoAmI << " done" << endl << whoAmI << " exit" << endl; << whoAmI << " exit" << endl; return 0; return 0;}//

// void* start_routine ( void* p ) { int whoAmI = (int)p; int whoAmI = (int)p; int whoAmICopy = whoAmI; int whoAmICopy = whoAmI; cout << whoAmI << " processing" << endl; cout << whoAmI << " processing" << endl; if (whoAmI==0) { //is this thread 0? if (whoAmI==0) { //is this thread 0? //make the global var point to my local var //make the global var point to my local var ::whoAmIPointer = &whoAmI; ::whoAmIPointer = &whoAmI; sched_yield(); sched_yield(); sleep( 5 ); sleep( 5 ); } else { } else { //this is not thread 0 so wait until thread 0 sets the global var //this is not thread 0 so wait until thread 0 sets the global var // that points to thread 0's local var. // that points to thread 0's local var. while (::whoAmIPointer==NULL) { while (::whoAmIPointer==NULL) { sched_yield(); sched_yield(); } //change thread 0's local var //change thread 0's local var *::whoAmIPointer = 92; *::whoAmIPointer = 92; } if (whoAmI!=whoAmICopy) { if (whoAmI!=whoAmICopy) { cout << "Hey! Wait a minute! Somebody changed who I am from " cout << "Hey! Wait a minute! Somebody changed who I am from " << whoAmICopy << " to " << whoAmI << "!" << endl; << whoAmICopy << " to " << whoAmI << "!" << endl; } cout << whoAmI << " done" << endl cout << whoAmI << " done" << endl << whoAmI << " exit" << endl; << whoAmI << " exit" << endl; return 0; return 0;}// How could this ever be true (if threads didn’t share stack memory)?

/* This program demonstrates that, although stack variables are not shared among threads, stack memory (_all_ process memory) is indeed shared by threads. g++ -o sharedStack.exe sharedStack.cpp -lpthread -lm -lrt */ #include #include using namespace std; const int N = 2; //max number of threads //this will be a pointer to a local variable in thread 0. static int* whoAmIPointer = NULL; // void* start_routine ( void* p ) { int whoAmI = (int)p; int whoAmI = (int)p; int whoAmICopy = whoAmI; int whoAmICopy = whoAmI; cout << whoAmI << " processing" << endl; cout << whoAmI << " processing" << endl; if (whoAmI==0) { //is this thread 0? if (whoAmI==0) { //is this thread 0? //make the global var point to my local var //make the global var point to my local var ::whoAmIPointer = &whoAmI; ::whoAmIPointer = &whoAmI; sched_yield(); sched_yield(); sleep( 5 ); sleep( 5 ); } else { } else { //this is not thread 0 so wait until thread 0 sets the global var //this is not thread 0 so wait until thread 0 sets the global var // that points to thread 0's local var. // that points to thread 0's local var. while (::whoAmIPointer==NULL) { while (::whoAmIPointer==NULL) { sched_yield(); sched_yield(); } //change thread 0's local var //change thread 0's local var *::whoAmIPointer = 92; *::whoAmIPointer = 92; } if (whoAmI!=whoAmICopy) { if (whoAmI!=whoAmICopy) { cout << "Hey! Wait a minute! Somebody changed who I am from " cout << "Hey! Wait a minute! Somebody changed who I am from " << whoAmICopy << " to " << whoAmI << "!" << endl; << whoAmICopy << " to " << whoAmI << "!" << endl; } cout << whoAmI << " done" << endl cout << whoAmI << " done" << endl << whoAmI << " exit" << endl; << whoAmI << " exit" << endl; return 0; return 0;}// int main ( const int argc, const char* const argv[] ) { pthread_t thread[::N]; //for thread id storage pthread_t thread[::N]; //for thread id storage //create N threads //create N threads for (int i=0; i< ::N; i++) { for (int i=0; i< ::N; i++) { pthread_create( &thread[i], 0, start_routine, (void*)i ); pthread_create( &thread[i], 0, start_routine, (void*)i ); cout << "main: thread " << i << " created with id=" << thread[i] cout << "main: thread " << i << " created with id=" << thread[i] << endl; << endl; } //wait for the N threads to finish //wait for the N threads to finish for (int i=0; i< ::N; i++) { for (int i=0; i< ::N; i++) { void* v; void* v; cout << "main: wait" << endl; cout << "main: wait" << endl; pthread_join( thread[i], &v ); pthread_join( thread[i], &v ); } cout << "main: returning" << endl; cout << "main: returning" << endl; return 0; return 0;}// complete example

WIN32, THREADS, & FIBERS

Win32 thread functions  CreateThread  Creates a thread to execute within the virtual address space of the calling process.  ExitThread  Ends the calling thread.  TerminateThread  Terminates a thread.  WaitForSingleObject  Waits until the specified object is in the signaled state or the time-out interval elapses.  GetExitCodeThread  Retrieves the termination status of the specified thread.

Win32 threads & fibers  Fibers (in win32 – not available in Linux)  a lightweight thread  owned by thread  Threads are preemptively scheduled.  Fibers are not preemptively scheduled.  When thread is preempted, so is fiber.  When thread is resumed, so is fiber.  may be scheduled by the owning thread

Win32 fibers  “A fiber is a unit of execution that must be manually scheduled by the application. Fibers run in the context of the threads that schedule them. Each thread can schedule multiple fibers. In general, fibers do not provide advantages over a well-designed multithreaded application. However, using fibers can make it easier to port applications that were designed to schedule their own threads.”  from us/library/ms682661%28v=vs.85%29.aspx us/library/ms682661%28v=vs.85%29.aspxhttp://msdn.microsoft.com/en- us/library/ms682661%28v=vs.85%29.aspx

Win32 fibers  “Fibers are not preemptively scheduled. You schedule a fiber by switching to it from another fiber. The system still schedules threads to run. When a thread running fibers is preempted, its currently running fiber is preempted but remains selected. The selected fiber runs when its thread runs.”  from us/library/ms682661%28v=vs.85%29.aspx us/library/ms682661%28v=vs.85%29.aspxhttp://msdn.microsoft.com/en- us/library/ms682661%28v=vs.85%29.aspx

SOLARIS THREADS API

Table 7. Threads and pthreads functions (from Solaris threads APILinux POSIX threads APIDescription thr_create()pthread_create()Creates a new thread of control. thr_exit()pthread_exit()Terminates the execution of the calling thread. thr_join()pthread_join()Suspends the calling thread until the target thread completes. thr_kill()pthread_kill()Sends a signal to another thread. thr_self()pthread_self()Returns the thread ID of the calling process. thr_yield()sched_yield()Makes the current thread yield to another thread. thr_getprio()pthread_getschedparam()Retrieves a thread's priority parameters. thr_setprio()pthread_setschedparam()Modifies a thread's priority parameters. thr_getspecific()pthread_getspecific()Binds a new thread-specific value to the key. thr_setspecific()pthread_setspecific()Binds a new thread-specific value to the key. thr_getconcurrency()pthread_getconcurrency()Gets thread concurrency level. thr_setconcurrency()pthread_setconcurrency()Sets thread concurrency level. thr_sigsetmask()pthread_sigmask()Changes or examines the calling thread's signal mask. thr_keycreate()pthread_key_create()Creates a key that locates data specific to a thread. N/Apthread_key_delete()Deletes a key that locates data specific to a thread. thr_suspend()N/ASuspends the execution of the specified thread. thr_continue()N/AResumes the execution of a suspended thread. fork1()fork()Regular fork. forkall()N/AReplicate all forks.

Threads and Java  Two approaches: 1.subclass Thread 2.implement Runnable

class PrimeThread extends Thread { long minPrime; long minPrime; PrimeThread ( long minPrime ) { PrimeThread ( long minPrime ) { this.minPrime = minPrime; this.minPrime = minPrime; } public void run ( ) { public void run ( ) { // compute primes larger than minPrime // compute primes larger than minPrime } } PrimeThread p = new PrimeThread( 143 ); p.start();

class PrimeRun implements Runnable { long minPrime; long minPrime; PrimeRun ( long minPrime ) { PrimeRun ( long minPrime ) { this.minPrime = minPrime; this.minPrime = minPrime; } public void run ( ) { public void run ( ) { // compute primes larger than minPrime // compute primes larger than minPrime } } PrimeRun p = new PrimeRun( 143 ); new Thread( p ).start();

Java assignment: Find the min array value in parallel.  Write a Java program that: 1.Initializes an int array of N random values. 2.Write a function that finds the min value. 3.Create two threads. One finds the min value in the first half; the other finds the min value in the second half.