A thread is a basic unit of CPU utilization, consisting of a program counter, a stack, and a set of registers. Threads within the same process share resources such as memory, file descriptors, and signal handlers. This lightweight nature of threads makes them ideal for performing multiple tasks concurrently within a single program.
In Linux, thread functions are declared in the <pthread.h>
header file. POSIX threads, or pthreads, provide a standard API for multithreading across UNIX-like operating systems, including Linux, macOS, FreeBSD, and OpenBSD.
Threads can be created using the pthread_create()
function. The syntax is as follows:
#include <iostream>
#include <pthread.h>
using namespace std;
void* print_message(void* message) {
cout << "Thread message: " << (char*)message << endl;
return nullptr;
}
int main() {
pthread_t thread;
const char* message = "Hello from the thread!";
pthread_create(&thread, NULL, print_message, (void*)message);
pthread_join(thread, NULL);
cout << "Main thread finished execution" << endl;
return 0;
}
Output:
Thread message: Hello from the thread!
Main thread finished execution
Threads can be terminated using the pthread_exit()
function. This is typically called when a thread completes its work.
pthread_exit(NULL);
Joining Threads
The pthread_join()
function allows the main thread to wait for the termination of a child thread. This ensures that the main thread does not terminate before its child threads.
pthread_join(thread, NULL);
#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;
void* print_message(void*) {
sleep(1);
cout << "Child thread executed" << endl;
return nullptr;
}
int main() {
pthread_t thread;
pthread_create(&thread, NULL, print_message, NULL);
pthread_join(thread, NULL);
cout << "Main thread finished execution" << endl;
return 0;
}
Output:
Child thread executed
Main thread finished execution
Detaching Threads
The pthread_detach()
function allows a thread to execute independently of the main thread, meaning the main thread does not need to wait for it to finish.
pthread_detach(thread);
#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;
void* print_message(void*) {
sleep(1);
cout << "Child thread executed independently" << endl;
return nullptr;
}
int main() {
pthread_t thread;
pthread_create(&thread, NULL, print_message, NULL);
pthread_detach(thread);
cout << "Main thread finished execution" << endl;
return 0;
}
Main thread finished execution
Child thread executed independently
Multiple arguments can be passed to a thread using a structure. This allows complex data types to be handled within the thread’s callback function.
Example: Passing Arguments to Threads
#include <iostream>
#include <pthread.h>
using namespace std;
struct ThreadData {
int thread_id;
const char* message;
};
void* print_data(void* thread_arg) {
ThreadData* data = (ThreadData*)thread_arg;
cout << "Thread ID: " << data->thread_id << ", Message: " << data->message << endl;
return nullptr;
}
int main() {
pthread_t threads[3];
ThreadData thread_data[3];
for (int i = 0; i < 3; ++i) {
thread_data[i].thread_id = i;
thread_data[i].message = "Hello from the thread!";
pthread_create(&threads[i], NULL, print_data, (void*)&thread_data[i]);
}
for (int i = 0; i < 3; ++i) {
pthread_join(threads[i], NULL);
}
return 0;
}
Thread ID: 0, Message: Hello from the thread!
Thread ID: 1, Message: Hello from the thread!
Thread ID: 2, Message: Hello from the thread!