A commonly used
parallel programming pattern
- A commonly used
parallel programming
pattern:
main( )
{
Prepare data1;
Spawn N "worker" threads to process data1;
Wait for all threads to complete processing
Prepare data2;
Spawn N "worker" threads to process data2;
Wait for all threads to complete processing
....
}
|
- Graphical
depiction of
each step:
|
Detached and
Joinable
threads
- There are
2 kinds of
threads in
the PThread API:
- Detached
threads
- Joinable
threads
|
-
Detached
threads:
- A detached
thread is an
"independent"
thread
- When a
detached
thread
terminates, its
resources
are
released back
to the system
immediately
|
-
Joinable
threads:
- A joinable
thread is a
"dependent"
thread
- When a
joinable
thread
terminates, its
resources
are
retained until
the thread
joins
with its
creator thread
|
- The
default
setting of
pthread_create( ) will
create a
joinable
thread
|
How to
"join" (= wait for) a
joinable thread
to finish
- When the main thread
creates a
"worker" thread, it must
record its
thread ID:
pthread_t tid;
if ( pthread_create(&tid, NULL, worker, &n) != 0 ) // Create thread
{
perror("pthread_create"); // Print error message
exit(1);
}
|
- The main thread can
"join" (= wait for)
a joinable thread with the
pthread_join( )
call:
pthread_join(pthread_t threadID, void **retval);
threadID = the thread ID returned by pthread_create( )
retval = return value returned by the exiting thread
Example:
pthread_join( tid, NULL ); // NULL = ignore the return value
|
|
Example on using
thread_join( )
- Consider the following
program where
main( ) does
not
join with the
worker thread:
void *worker( )
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10000000; j++); // Slow thread down...
printf("*");
fflush(stdout);
}
}
int main(int argc, char *argv[])
{
pthread_t tid;
if ( pthread_create(&tid, NULL, worker, NULL) != 0 ) // Create thread
{
perror("pthread_create"); // Print error message
exit(1);
}
// Do NOT join (wait)
}
|
- Result:
nothing is
printed
(because
main( )
exited before
worker
prints)
|
DEMO:
demo/pthread/join01.c
Example on using
thread_join( )
- We change it so
main( ) will
pthread_join( ) with the
worker thread:
void *worker( )
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10000000; j++); // Slow thread down...
printf("*");
fflush(stdout);
}
}
int main(int argc, char *argv[])
{
pthread_t tid;
if ( pthread_create(&tid, NULL, worker, NULL) != 0 ) // Create thread
{
perror("pthread_create"); // Print error message
exit(1);
}
pthread_join(&tid, NULL); // Join with (wait for) worker to finish
}
|
- Result:
********** is
printed
(because
main( )
waited for
worker( )
exit)
|
DEMO:
demo/pthread/join01b.c
How to wait for
multiple worker threads
to complete execution
- Program that
creates a
group of
worker
threads:
void *worker(int *id) // Not syntactically correct, but easier to code...
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10000000; j++); // Slow thread down...
printf("%d", *id);
}
}
int main(int argc, char *argv[])
{
pthread_t tid[4];
int arg[4];
for ( int i = 0; i < 4; i++ )
{
arg[i] = i;
if ( pthread_create(&tid[i], NULL, worker, &arg[i]) != 0 ){
perror("pthread_create"); // Print error message
exit(1);
}
}
for ( int i = 0; i < 4; i++ )
pthread_join(tid[i], NULL);
}
|
|
How to wait for
multiple worker threads
to complete execution
-
Create the
group of
threads and
save each
thread ID:
void *worker(int *id) // Not syntactically correct, but easier to code...
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10000000; j++); // Slow thread down...
printf("%d", *id);
}
}
int main(int argc, char *argv[])
{
pthread_t tid[4];
int arg[4];
for ( int i = 0; i < 4; i++ )
{
arg[i] = i;
if ( pthread_create(&tid[i], NULL, worker, &arg[i]) != 0 ){
perror("pthread_create"); // Print error message
exit(1);
}
}
for ( int i = 0; i < 4; i++ )
pthread_join(tid[i], NULL);
}
|
|
How to wait for
multiple worker threads
to complete execution
-
Wait for
every
thread to
finish:
void *worker(int *id) // Not syntactically correct, but easier to code...
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10000000; j++); // Slow thread down...
printf("%d", *id);
}
}
int main(int argc, char *argv[])
{
pthread_t tid[4];
int arg[4];
for ( int i = 0; i < 4; i++ )
{
arg[i] = i;
if ( pthread_create(&tid[i], NULL, worker, &arg[i]) != 0 ){
perror("pthread_create"); // Print error message
exit(1);
}
}
for ( int i = 0; i < 4; i++ )
pthread_join(tid[i], NULL);
}
|
|
DEMO:
demo/pthread/join02.c
❮
❯