This article will use two examples to practically use pthread for multithreading programming, mainly including two parts:
Parallel calculation of the PI value by data division
Thread pool development based on the producer-consumer model, with the specific business logic simplified, focusing on thread management and synchronization
1 Calculating Pi
1.1 Brief Idea
According to the Leibniz formula, calculate more times with multithreading to approximate $\pi$. Use multithreading to divide data, i.e., each thread handles part of the data to accelerate the process. At the same time, since multithreading access to the global result may have conflicts, mutexes and semaphores are used to organize threads to orderly add local results to the global result.
Use a task queue as a buffer between producers and consumers, where each element in the task queue contains the function to execute and the function parameters, corresponding code as follows:
On the producer side, the thread_pool_enqueue function is used to add tasks to the task queue. When a producer produces a task, it first uses the thread pool’s mutex pool->mutex to protect the task queue, preventing multiple threads from modifying the task queue simultaneously, then uses the condition variable pool->cond to notify consumers of new tasks arriving.
On the consumer side, the thread_pool_worker function is used to take tasks from the task queue and execute them. When a consumer takes a task from the task queue, it uses the mutex pool->mutex to protect the task queue. If the task queue is empty, the consumer will be blocked by the condition variable pool->mutex, waiting for the producer to add new tasks to the task queue.
Starting the thread pool includes initializing the task queue, semaphores, starting consumer threads; shutting down the thread pool mainly involves waiting for all threads to finish running; both implementations are as follows: