The principle and implementation of the thread pool of Linux platform

Source: Internet
Author: User

Transferred from: http://blog.csdn.net/lmh12506/article/details/7753952

Some time ago on GitHub opened a library, ready to implement their own thread pool, because the change of work, has not been achieved, refer to this article is ready to start to achieve.

When do I need to create a thread pool? Simply put, if an application needs to create and destroy threads frequently, and the task executes in a very short time, the overhead of creating and destroying threads is not negligible, and this is the opportunity for the thread pool to appear. If the thread creation and destruction times are negligible compared to the execution time of the task, there is no need to use the thread pool.

The following is a thread pool created under the Linux system in C language. The thread pool maintains a list of tasks (each cthread_worker structure is a task).

The Pool_init () function pre-creates max_thread_num threads, each with a thread_routine () function. In this function

    1. while (pool->cur_queue_size = = 0)
    2. {
    3. Pthread_cond_wait (& (Pool->queue_ready),& (Pool->queue_lock));
    4. }

Indicates that the thread is in a blocked wait state if there are no tasks in the task list. Otherwise, the task is removed from the queue and executed.

The Pool_add_worker () function adds a task to the task list of the thread pool and wakes up a blocked thread (if any) by calling Pthread_cond_signal (& (Pool->queue_ready)) after joining. )。

The Pool_destroy () function is used to destroy the thread pool, and the task in the thread pool task list will no longer be executed, but the running thread will keep the task running and then exit.

The complete code is posted below

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <pthread.h>
  6. #include <assert.h>
  7. /*
  8. * All running and waiting tasks in the thread pool are a cthread_worker
  9. * Since all tasks are in the list, it is a linked list structure
  10. */
  11. typedef struct Worker
  12. {
  13. / * callback function, which is called when the task is run, or it can be declared as a different form * /
  14. void * (*process) (void *arg);
  15. void *arg; / * Parameters for callback function * /
  16. struct worker *next;
  17. } Cthread_worker;
  18. /* Thread pool structure */
  19. typedef struct
  20. {
  21. pthread_mutex_t Queue_lock;
  22. pthread_cond_t Queue_ready;
  23. / * Linked list structure, all waiting tasks in the thread pool * /
  24. Cthread_worker *queue_head;
  25. / * Whether to destroy the thread pool * /
  26. int shutdown;
  27. pthread_t *threadid;
  28. / * Number of active threads allowed in the thread pool * /
  29. int max_thread_num;
  30. / * Number of tasks currently waiting for queue * /
  31. int cur_queue_size;
  32. } Cthread_pool;
  33. int Pool_add_worker (void * (*process) (void *arg), void *arg);
  34. void *thread_routine (void *arg);
  35. static Cthread_pool *pool = NULL;
  36. void
  37. Pool_init (int max_thread_num)
  38. {
  39. Pool = (Cthread_pool *) malloc (sizeof (Cthread_pool));
  40. Pthread_mutex_init (& (Pool->queue_lock), NULL);
  41. Pthread_cond_init (& (Pool->queue_ready), NULL);
  42. Pool->queue_head = NULL;
  43. Pool->max_thread_num = Max_thread_num;
  44. pool->cur_queue_size = 0;
  45. Pool->shutdown = 0;
  46. Pool->threadid =
  47. (pthread_t *) malloc (Max_thread_num * sizeof (pthread_t));
  48. int i = 0;
  49. For (i = 0; i < max_thread_num; i++)
  50. {
  51. Pthread_create (& (Pool->threadid[i]), NULL, Thread_routine,
  52. NULL);
  53. }
  54. }
  55. /* Join the task to the thread pool */
  56. Int
  57. Pool_add_worker (void* (*process) (void *arg), void *arg)
  58. {
  59. / * Construct a new task * /
  60. Cthread_worker *newworker =
  61. (Cthread_worker *) malloc (sizeof (Cthread_worker));
  62. newworker->process = process;
  63. Newworker->arg = arg;
  64. Newworker->next = NULL; / * Don't forget to empty * *
  65. Pthread_mutex_lock (& (Pool->queue_lock));
  66. / * Add tasks to the wait queue * /
  67. Cthread_worker *member = pool->queue_head;
  68. if (member! = NULL)
  69. {
  70. While (member->next! = NULL)
  71. member = member->next;
  72. Member->next = Newworker;
  73. }
  74. Else
  75. {
  76. Pool->queue_head = Newworker;
  77. }
  78. ASSERT (Pool->queue_head! = NULL);
  79. pool->cur_queue_size++;
  80. Pthread_mutex_unlock (& (Pool->queue_lock));
  81. / * OK, wait for the queue to have a task, wake up a waiting thread;
  82. Note that if all threads are busy, this sentence has no effect */
  83. Pthread_cond_signal (& (Pool->queue_ready));
  84. return 0;
  85. }
  86. /* Destroys the thread pool, waiting for tasks in the queue to no longer be executed, but the running thread will always
  87. Run the task and then exit */
  88. Int
  89. Pool_destroy ()
  90. {
  91. if (pool->shutdown)
  92. return-1; / * Prevent two calls * /
  93. Pool->shutdown = 1;
  94. / * Wake up all waiting threads and the thread pool will be destroyed * /
  95. Pthread_cond_broadcast (& (Pool->queue_ready));
  96. / * Block waiting thread to quit or become a zombie * *
  97. int i;
  98. For (i = 0; i < pool->max_thread_num; i++)
  99. Pthread_join (Pool->threadid[i], NULL);
  100. Free (pool->threadid);
  101. / * Destroy the wait queue * /
  102. Cthread_worker *head = NULL;
  103. While (pool->queue_head! = NULL)
  104. {
  105. Head = pool->queue_head;
  106. Pool->queue_head = pool->queue_head->next;
  107. Free (head);
  108. }
  109. /* Condition variable and mutex do not forget to destroy */
  110. Pthread_mutex_destroy (& (Pool->queue_lock));
  111. Pthread_cond_destroy (& (Pool->queue_ready));
  112. Free (pool);
  113. / * It's a good habit to empty the pointer after destroying it.
  114. Pool=null;
  115. return 0;
  116. }
  117. void *
  118. Thread_routine (void *arg)
  119. {
  120. printf ("Starting thread 0x%x\n", pthread_self ());
  121. While (1)
  122. {
  123. Pthread_mutex_lock (& (Pool->queue_lock));
  124. / * If the wait queue is 0 and the thread pool is not destroyed, be in a blocked state;
  125. Pthread_cond_wait is an atomic operation that will be unlocked before waiting, and will be locked when awakened.
  126. While (pool->cur_queue_size = = 0 &&!pool->shutdown)
  127. {
  128. printf ("Thread 0x%x is waiting\n", pthread_self ());
  129. Pthread_cond_wait (& (Pool->queue_ready), & (Pool->queue_lock));
  130. }
  131. / * thread pool to be destroyed * /
  132. if (pool->shutdown)
  133. {
  134. / * Encounter Break,continue,return and other jump statements, do not forget to unlock the first * /
  135. Pthread_mutex_unlock (& (Pool->queue_lock));
  136. printf ("thread 0x%x would exit\n", pthread_self ());
  137. Pthread_exit (NULL);
  138. }
  139. printf ("Thread 0x%x is starting to work\n", pthread_self ());
  140. /*assert is a good helper for commissioning * *
  141. ASSERT (Pool->cur_queue_size! = 0);
  142. ASSERT (Pool->queue_head! = NULL);
  143. / * Wait for the queue length minus 1 and remove the header element from the list * /
  144. pool->cur_queue_size--;
  145. Cthread_worker *worker = pool->queue_head;
  146. Pool->queue_head = worker->next;
  147. Pthread_mutex_unlock (& (Pool->queue_lock));
  148. / * Call the callback function to perform the task * /
  149. (* (worker->process)) (Worker->arg);
  150. Free (worker);
  151. worker = NULL;
  152. }
  153. / * This sentence should not be reached * /
  154. Pthread_exit (NULL);
  155. }

Here is the test code

  1. void *
  2. Myprocess (void *arg)
  3. {
  4. printf ("ThreadID is 0x%x, working on Task%d\n", Pthread_self (), * (int *) arg);
  5. Sleep (1); / * Take a second to extend the execution time of the task */
  6. return NULL;
  7. }
  8. Int
  9. Main (int argc, char **argv)
  10. {
  11. Pool_init (3); / * Up to three active threads in a thread pool * /
  12. / * Put 10 tasks into the pool continuously * /
  13. int *workingnum = (int *) malloc (sizeof (int) *);
  14. int i;
  15. For (i = 0; i <; i++)
  16. {
  17. Workingnum[i] = i;
  18. Pool_add_worker (Myprocess, &workingnum[i]);
  19. }
  20. / * Wait for all tasks to complete * /
  21. Sleep (5);
  22. / * Destroy thread pool * /
  23. Pool_destroy ();
  24. Free (workingnum);
  25. return 0;
  26. }

Put all of the above code into the threadpool.c file,
In the Linux input compilation command
$ gcc-o ThreadPool threadpool.c-lpthread

Here are the results of the operation
Starting thread 0xb7df6b90
Thread 0xb7df6b90 is waiting
Starting thread 0xb75f5b90
Thread 0xb75f5b90 is waiting
Starting thread 0xb6df4b90
Thread 0xb6df4b90 is waiting
Thread 0xb7df6b90 is starting to work
ThreadID is 0xb7df6b90, working on task 0
Thread 0xb75f5b90 is starting to work
ThreadID is 0xb75f5b90, working on Task 1
Thread 0xb6df4b90 is starting to work
ThreadID is 0xb6df4b90, working on Task 2
Thread 0xb7df6b90 is starting to work
ThreadID is 0xb7df6b90, working on task 3
Thread 0xb75f5b90 is starting to work
ThreadID is 0xb75f5b90, working on Task 4
Thread 0xb6df4b90 is starting to work
ThreadID is 0xb6df4b90, working on Task 5
Thread 0xb7df6b90 is starting to work
ThreadID is 0xb7df6b90, working on task 6
Thread 0xb75f5b90 is starting to work
ThreadID is 0xb75f5b90, working on task 7
Thread 0xb6df4b90 is starting to work
ThreadID is 0xb6df4b90, working on task 8
Thread 0xb7df6b90 is starting to work
ThreadID is 0xb7df6b90, working on task 9
Thread 0xb75f5b90 is waiting
Thread 0xb6df4b90 is waiting
Thread 0xb7df6b90 is waiting
Thread 0xb75f5b90 would exit
Thread 0xb6df4b90 would exit
Thread 0xb7df6b90 would exit

The principle and implementation of the thread pool of Linux platform

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.