POSIX threads define a standard thread library implemented by many Unix systems.
In Linux, include pthread.h and compile with the -lpthread option to use POSIX threads.
Threads are created with the pthread_create function. pthread_create takes 4 parameters:
To terminate, a thread should call pthread_exit(void*) where the parameter is a pointer to a structure containing the return value of the thread, or NULL if no information need be returned.
#include <iostream>
#include <unistd.h>
#include <pthread.h>
/**
* POSIX threads demo: starts two timer threads.
*
* Compile with
* g++ -o pthreads.x pthreads.cpp -lpthread
* if the -lpthread option is not specified the program will crash when run.
*/
/**
* A structure to hold the arguments to the timer threads.
*/
struct timer_args
{
int id;
int ticks;
int interval;
};
/**
* A structure to hold the information returned from the timer threads.
*/
struct timer_result
{
int time;
};
/**
* The entry point for the timer threads.
*/
void *timer(void *p)
{
timer_args *args = reinterpret_cast< timer_args * >(p);
for (int tick = 0; tick < args->ticks; tick++)
{
sleep(args->interval);
std::cout << "timer " << args->id << ": " << (tick + 1) * args->interval
<< " seconds have elapsed" << std::endl;
}
timer_result *result = new timer_result;
result->time = args->ticks * args->interval;
delete args;
return result;
}
int main()
{
// set up arguments to pass to threads
timer_args *args1 = new timer_args(), *args2 = new timer_args();
args1->id = 1;
args1->ticks = 10;
args1->interval = 3;
args2->id = 2;
args2->ticks = 3;
args2->interval = 10;
// declare space for thread ids
pthread_t timer1, timer2;
// create threads
pthread_create(&timer1, NULL, timer, args1);
pthread_create(&timer2, NULL, timer, args2);
// detach threads so memory used by the thread handler will be automatically
// released when the threads terminate
pthread_detach(timer1);
pthread_detach(timer2);
// exit main -- if main simply runs through to } the whole process terminates
pthread_exit(NULL);
}
#include <iostream>
#include <cstdlib>
#include <pthread.h>
/**
* A demonstration of allowing threads unsynchronized access to
* shared data structures. Here we have two threads incrementing
* a shared 64-bit counter. If one thread is interrupted in the middle
* of its increment, the count will be off.
*/
long long global = 0;
bool running = true;
void *counter(void *p)
{
long long *count = reinterpret_cast< long long * >(p);
long long local = 0;
for (long long i = 0; i < *count; i++)
{
local++;
// complicated way of incrementing a 64-bit int:
// 1) increment the low word
// 2) if the low word rolled over, increment the high word
// split 64-bit int into two 32-bit words
int low = *(reinterpret_cast< int * >(&global));
int high = *(reinterpret_cast< int * >(&global + 1));
// increment
low++;
if (low == 0)
high++;
// store result back
*(reinterpret_cast< int * >(&global)) = low;
*(reinterpret_cast< int * >(&global + 1)) = high;
}
long long *result = new long long(*count);
delete count;
return result;
}
int main(int argc, char **argv)
{
if (argc < 2)
{
std::cerr << "USAGE: " << argv[0] << " n" << std::endl;
return 1;
}
long long count = atoll(argv[1]);
if (count < 0)
{
std::cerr << argv[0] << ": n must be positive" << std::endl;
return 1;
}
// create arguments to pass to counter threads
long long *count1 = new long long(count), *count2 = new long long(count);
// create threads
pthread_t counter1, counter2;
pthread_create(&counter1, NULL, counter, count1);
pthread_create(&counter2, NULL, counter, count2);
// wait for threads to terminate
long long *return1, *return2;
pthread_join(counter1, reinterpret_cast< void ** >(&return1));
pthread_join(counter2, reinterpret_cast< void ** >(&return2));
// display results
std::cout << "Threads preformed " << *return1 + *return2 << " increments"
<< std::endl
<< "Shared global counter is now " << global
<< std::endl;
// free memory allocated by threads for their return values
delete return1;
delete return2;
return 0;
}
This code can also be downloaded from the files
pthreads.cpp and
counter.cpp.