Home System Tutorial LINUX The use of thread pool under Linux C

The use of thread pool under Linux C

Feb 13, 2024 am 11:33 AM
linux linux tutorial linux system linux command shell script embeddedlinux Getting started with linux linux learning

Do you often encounter the problem that the server load is too high and cannot be accessed normally? Then, you need to understand a very important concept in Linux systems-thread pool. By properly configuring the thread pool, you can effectively avoid server overload and improve system stability and reliability.

Thread pool is also a multi-thread processing method. The "producer" thread proposes tasks and adds them to the "task queue", and then some threads automatically complete the tasks on the "task queue".

Linux C下线程池的使用

Multi-threaded programming, create a thread, specify it to complete a certain task, and wait for the thread to exit. Although it can meet programming needs, when we need to create a large number of threads, a large amount of CPU may be consumed during the creation and destruction of threads, adding a lot of overhead. For example: copy of folder, response from WEB server.

The thread pool is used to solve a problem like this, which can reduce the overhead caused by frequent creation and destruction of threads.

Thread pool technology idea: Generally, pre-created thread technology is used, that is, a certain number of required threads are created in advance. After these threads are created in advance, assuming there are no tasks in the "task queue", then let these threads sleep. Once there is a task, wake up the thread to execute the task. After the task is executed, there is no need to destroy the thread until you want to When exiting or shutting down, at this time, you call the function that destroys the thread pool to destroy the thread.

The thread will not be destroyed after completing the task, but will automatically execute the next task. Moreover, when there are many tasks, you can have a functional interface to increase the number of threads. When there are few tasks, you can have a functional interface to destroy some threads.

If the time to create and destroy threads is negligible compared to the time to execute tasks, then we do not need to use a thread pool in this case.

"Task Queue" is a shared resource with "mutually exclusive access"

Linux C下线程池的使用

The thread pool is essentially a data structure and requires a structure to describe it:

struct pthread_pool //线程池的实现 
{ 
 //一般会有如下成员 
 
 //互斥锁,用来保护这个“任务队列” 
 pthread_mutex_t lock; //互斥锁  
  
 //线程条件变量 表示“任务队列”是否有任务 
 pthread_cond_t cond; //条件变量 
  
 bool shutdown; //表示是否退出程序 bool:类型 false / true 
 
 //任务队列(链表),指向第一个需要指向的任务 
 //所有的线程都从任务链表中获取任务 "共享资源" 
 struct task * task_list; 
  
 //线程池中有多个线程,每一个线程都有tid, 需要一个数组去保存tid 
 pthread_t * tids; //malloc()  
  
 //线程池中正在服役的线程数,当前线程个数 
 unsigned int active_threads; 
  
 //线程池任务队列最大的任务数量 
 unsigned int max_waiting_tasks; 
  
 //线程池任务队列上当前有多少个任务 
 unsigned int cur_waiting_tasks; 
  
 //...... 
 
}; 
 
//任务队列(链表)上面的任务结点,只要能够描述好一个任务就可以了, 
//线程会不断地任务队列取任务 
struct task  //任务结点  
{ 
 // 1. 任务结点表示的任务,“函数指针”指向任务要执行的函数(cp_file) 
 void*(* do_task)(void * arg); 
  
 //2. 指针,指向任务指向函数的参数(文件描述符) 
 void * arg; 
  
 //3. 任务结点类型的指针,指向下一个任务 
 struct task * next; 
}; 
Copy after login

The thread pool framework code is as follows, the functions are filled in by yourself:

Function interfaces required to operate the thread pool: pthread_pool.c, pthread_pool.h

Imagine the "thread pool" as an outsourcing company. What you need to complete is to operate the function interface provided by the thread pool.

pthread_pool.c

#include "pthread_pool.h" 
 
/* 
 init_pool: 线程池初始化函数,初始化指定的线程池中有thread_num个初始线程 
 @pool:指针,指向您要初始化的那个线程池 
 @threa_num: 您要初始化的线程池中开始的线程数量 
 返回值:  
  成功 0 
  失败 -1 
*/ 
 
int init_pool(pthread_pool * pool , unsigned int threa_num) 
{ 
 //初始化线程池的结构体 
  
 //初始化线程互斥锁 
 pthread_mutex_init(&pool->lock, NULL); 
  
 //初始化线程条件变量 
 pthread_cond_init(&pool->cond, NULL); 
 
 pool->shutdown = false ;// 不退出 
 
 pool->task_list = (struct task*)malloc(sizeof(struct task)); 
 
 pool->tids = (pthread_t *)malloc(sizeof(pthread_t) * MAX_ACTIVE_THREADS); 
 if(pool->task_list == NULL || pool->tids == NULL) 
 { 
  perror("malloc memery error"); 
  return -1; 
 } 
 
 pool->task_list->next = NULL; 
 
 //线程池中一开始初始化多少个线程来服役 
 pool->active_threads = threa_num; 
 
 //表示线程池中最多有多少个任务 
 pool->max_waiting_tasks = MAX_WAITING_TASKS; 
 
 //线程池中任务队列当前的任务数量 
 pool->cur_waiting_tasks = 0; 
 
 //创建thread_num个线程,并且让线程去执行任务调配函数, 
 //记录所有线程的tid 
 int i = 0; 
 for(i = 0; i tids)[i], NULL, routine, (void*)pool); 
  if(ret != 0) 
  { 
   perror("create thread error"); 
   return -1; 
  } 
 
  printf("[%lu]:[%s] ===> tids[%d]:[%lu]",pthread_self(), 
   __FUNCTION__, i , pool->tids[i]); 
 } 
 
 return 0; 
} 
 
/* 
 routine: 任务调配函数。 
  所有线程开始都执行此函数,此函数会不断的从线程池的任务队列 
  中取下任务结点,去执行。 
   
  任务结点中包含“函数指针” h "函数参数" 
*/ 
 
void * routine(void * arg) 
{ 
 //arg表示你的线程池的指针 
  
 while() 
 { 
  //获取线程互斥锁,lock  
   
  //当线程池没有结束的时候,不断地从线程池的任务队列取下结点 
  //去执行。 
   
  //释放线程互斥锁,unlock 
   
  //释放任务结点 
 } 
} 
 
/* 
 destroy_pool: 销毁线程池,销毁前要保证所有的任务已经完成 
*/ 
 
int destroy_pool(pthread_pool * pool) 
{ 
 //释放所有空间 等待任务执行完毕(join)。 
 //唤醒所有线程 
 //利用join函数回收每一个线程资源。 
} 
 
/* 
 add_task:给任务队列增加任务, 把do_task指向的任务(函数指针)和 
  arg指向的参数保存到一个任务结点,添加到pool任务队列中。 
   
 @pool : 您要添加任务的线程池 
 @do_task : 您需要添加的任务(cp_file) 
 @arg: 您要执行的任务的参数(文件描述符) 
*/ 
 
int add_task(pthread_pool *pool,void*(* do_task)(void * arg), void*arg) 
{ 
 //把第二个参数和第三个参数封装成struct task  
  
 //再把它添加到 pool->task 任务队列中去 
  
 //注意任务队列是一个共享资源 
  
 //假如任务后要唤醒等待的线程。 
} 
 
//如果任务多的时候,往线程池中添加线程  pthread_create 
int add_threads(pthread_pool * pool, unsigned int num); 
{ 
 //新创建num个线程,让每一个线程去执行线程调配函数 
  
 //将每一个新创建的线程tid,添加到pool-> tids  
} 
 
//如果任务少的时候,减少线程池中线程的数量 pthread_cancel join 
int remove_threads(pthread_pool * pool, unsigned int num) 
{ 
 //用pthread_cancel取消num个线程  
 //利用pthread_join函数去回收资源。 
} 
Copy after login

pthread_pool.h

#ifndef __PTHREAD_POOL_H__ 
#define __PTHREAD_POOL_H__ 
 
//表示线程池中最多有多少个线程 
#define MAX_ACTIVE_THREADS 20 
 
//表示线程池中最多有多少个任务 
#define MAX_WAITING_TASKS 1024 
 
//任务队列(链表)上面的任务结点,只要能够描述好一个任务就可以了, 
//线程会不断地任务队列取任务 
struct task  //任务结点  
{ 
 // 1. 任务结点表示的任务,“函数指针”指向任务要执行的函数(cp_file) 
 void*(* do_task)(void * arg); 
  
 //2. 指针,指向任务指向函数的参数(文件描述符) 
 void * arg; 
  
 //3. 任务结点类型的指针,指向下一个任务 
 struct task * next; 
}; 
 
struct pthread_pool //线程池的实现 
{ 
 //一般会有如下成员 
 
 //互斥锁,用来保护这个“任务队列” 
 pthread_mutex_t lock; //互斥锁  
  
 //线程条件变量 表示“任务队列”是否有任务 
 pthread_cond_t cond; //条件变量 
  
 bool shutdown; //表示是否退出程序 bool:类型 false / true 
 
 //任务队列(链表),指向第一个需要指向的任务 
 //所有的线程都从任务链表中获取任务 "共享资源" 
 struct task * task_list; 
  
 //线程池中有多个线程,每一个线程都有tid, 需要一个数组去保存tid 
 pthread_t * tids; //malloc()  
  
 //线程池中正在服役的线程数,当前线程个数 
 unsigned int active_threads; 
  
 //线程池任务队列最大的任务数量 
 unsigned int max_waiting_tasks; 
  
 //线程池任务队列上当前有多少个任务 
 unsigned int cur_waiting_tasks; 
  
 //...... 
 
}; 
 
/* 
 init_pool: 线程池初始化函数,初始化指定的线程池中有thread_num 
  个初始线程 
 @pool:指针,指向您要初始化的那个线程池 
 @threa_num: 您要初始化的线程池中开始的线程数量 
 返回值:  
  成功 0 
  失败 -1 
*/ 
 
int init_pool(pthread_pool * pool , unsigned int threa_num); 
 
/* 
 routine: 任务调配函数。 
  所有线程开始都执行此函数,此函数会不断的从线程池的任务队列 
  中取下任务结点,去执行。 
   
  任务结点中包含“函数指针” h "函数参数" 
*/ 
 
void * routine(void * arg); 
 
/* 
 destroy_pool: 销毁线程池,销毁前要保证所有的任务已经完成 
*/ 
 
int destroy_pool(pthread_pool * pool); 
 
/* 
 add_task:给任务队列增加任务, 把do_task指向的任务(函数指针)和 
  arg指向的参数保存到一个任务结点,添加到pool任务队列中。 
   
 @pool : 您要添加任务的线程池 
 @do_task : 您需要添加的任务(cp_file) 
 @arg: 您要执行的任务的参数(文件描述符) 
*/ 
 
int add_task(pthread_pool *pool,void*(* do_task)(void * arg), void*arg); 
 
//如果任务多的时候,往线程池中添加线程  pthread_create 
int add_threads(pthread_pool * pool, unsigned int num); 
 
 
//如果任务少的时候,减少线程池中线程的数量 pthread_cancel join 
int remove_threads(pthread_pool * pool, unsigned int num); 
 
#endif 
Copy after login

The above is the detailed content of The use of thread pool under Linux C. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to use docker desktop How to use docker desktop Apr 15, 2025 am 11:45 AM

How to use Docker Desktop? Docker Desktop is a tool for running Docker containers on local machines. The steps to use include: 1. Install Docker Desktop; 2. Start Docker Desktop; 3. Create Docker image (using Dockerfile); 4. Build Docker image (using docker build); 5. Run Docker container (using docker run).

Difference between centos and ubuntu Difference between centos and ubuntu Apr 14, 2025 pm 09:09 PM

The key differences between CentOS and Ubuntu are: origin (CentOS originates from Red Hat, for enterprises; Ubuntu originates from Debian, for individuals), package management (CentOS uses yum, focusing on stability; Ubuntu uses apt, for high update frequency), support cycle (CentOS provides 10 years of support, Ubuntu provides 5 years of LTS support), community support (CentOS focuses on stability, Ubuntu provides a wide range of tutorials and documents), uses (CentOS is biased towards servers, Ubuntu is suitable for servers and desktops), other differences include installation simplicity (CentOS is thin)

What to do if the docker image fails What to do if the docker image fails Apr 15, 2025 am 11:21 AM

Troubleshooting steps for failed Docker image build: Check Dockerfile syntax and dependency version. Check if the build context contains the required source code and dependencies. View the build log for error details. Use the --target option to build a hierarchical phase to identify failure points. Make sure to use the latest version of Docker engine. Build the image with --t [image-name]:debug mode to debug the problem. Check disk space and make sure it is sufficient. Disable SELinux to prevent interference with the build process. Ask community platforms for help, provide Dockerfiles and build log descriptions for more specific suggestions.

How to view the docker process How to view the docker process Apr 15, 2025 am 11:48 AM

Docker process viewing method: 1. Docker CLI command: docker ps; 2. Systemd CLI command: systemctl status docker; 3. Docker Compose CLI command: docker-compose ps; 4. Process Explorer (Windows); 5. /proc directory (Linux).

What computer configuration is required for vscode What computer configuration is required for vscode Apr 15, 2025 pm 09:48 PM

VS Code system requirements: Operating system: Windows 10 and above, macOS 10.12 and above, Linux distribution processor: minimum 1.6 GHz, recommended 2.0 GHz and above memory: minimum 512 MB, recommended 4 GB and above storage space: minimum 250 MB, recommended 1 GB and above other requirements: stable network connection, Xorg/Wayland (Linux)

Detailed explanation of docker principle Detailed explanation of docker principle Apr 14, 2025 pm 11:57 PM

Docker uses Linux kernel features to provide an efficient and isolated application running environment. Its working principle is as follows: 1. The mirror is used as a read-only template, which contains everything you need to run the application; 2. The Union File System (UnionFS) stacks multiple file systems, only storing the differences, saving space and speeding up; 3. The daemon manages the mirrors and containers, and the client uses them for interaction; 4. Namespaces and cgroups implement container isolation and resource limitations; 5. Multiple network modes support container interconnection. Only by understanding these core concepts can you better utilize Docker.

What is vscode What is vscode for? What is vscode What is vscode for? Apr 15, 2025 pm 06:45 PM

VS Code is the full name Visual Studio Code, which is a free and open source cross-platform code editor and development environment developed by Microsoft. It supports a wide range of programming languages ​​and provides syntax highlighting, code automatic completion, code snippets and smart prompts to improve development efficiency. Through a rich extension ecosystem, users can add extensions to specific needs and languages, such as debuggers, code formatting tools, and Git integrations. VS Code also includes an intuitive debugger that helps quickly find and resolve bugs in your code.

vscode cannot install extension vscode cannot install extension Apr 15, 2025 pm 07:18 PM

The reasons for the installation of VS Code extensions may be: network instability, insufficient permissions, system compatibility issues, VS Code version is too old, antivirus software or firewall interference. By checking network connections, permissions, log files, updating VS Code, disabling security software, and restarting VS Code or computers, you can gradually troubleshoot and resolve issues.

See all articles