C語(yǔ)言學(xué)習(xí)項(xiàng)目——線程池原理及其實(shí)現(xiàn)
線程池介紹
線程池是一種用于管理和復(fù)用多個(gè)線程的技術(shù)。它由線程池管理器、工作隊(duì)列和一組線程組成。
線程池的主要目的是減少線程創(chuàng)建和銷毀的開(kāi)銷,并在任務(wù)到達(dá)時(shí)立即執(zhí)行任務(wù)。它以一種優(yōu)化的方式分配和控制線程,提供了一種高效的并發(fā)處理機(jī)制。
線程池的工作原理如下:
創(chuàng)建一個(gè)固定數(shù)量的線程池,初始化線程池中的線程。
當(dāng)有任務(wù)到達(dá)時(shí),線程池將任務(wù)放入工作隊(duì)列。
線程池中的空閑線程從工作隊(duì)列中獲取任務(wù)并執(zhí)行。
執(zhí)行完任務(wù)后,線程返回線程池并等待新的任務(wù)。
當(dāng)線程池不再需要時(shí),可以關(guān)閉線程池并釋放資源。
線程池的好處包括:
降低線程創(chuàng)建和銷毀的開(kāi)銷,節(jié)省系統(tǒng)資源。
控制并發(fā)線程數(shù)量,避免過(guò)多的線程競(jìng)爭(zhēng)導(dǎo)致系統(tǒng)性能下降。
提供任務(wù)調(diào)度和執(zhí)行的靈活性,可以根據(jù)需求動(dòng)態(tài)調(diào)整線程池配置。
提供統(tǒng)一的線程管理和監(jiān)控,方便調(diào)試和優(yōu)化應(yīng)用程序。
項(xiàng)目鏈接:
https://github.com/Pithikos/C-Thread-Poolgithub.com/Pithikos/C-Thread-Pool
API分析
這個(gè)項(xiàng)目使用C語(yǔ)言實(shí)現(xiàn)了最為簡(jiǎn)單的線程池技術(shù),初學(xué)者也可以通過(guò)這個(gè)項(xiàng)目快速理解并使用到自己的線程池,下面是這個(gè)項(xiàng)目所提供的API,所有API的介紹都在:thpool.h?中
threadpool?thpool_init(int num_threads)?初始化線程池,返回一個(gè)包含有num_threads個(gè)線程的線程池。
int thpool_add_work(threadpool, void (*function_p)(void*), void* arg_p);?添加工作(function_p)到線程工作隊(duì)列中,由線程池中的線程進(jìn)行調(diào)用。
void thpool_wait(threadpool);?等待線程池中所有任務(wù)執(zhí)行完成。
void thpool_pause(threadpool);?暫停當(dāng)前線程池中的所有線程。
void thpool_resume(threadpool);?恢復(fù)暫停中的線程池中的所有任務(wù)。
void?thpool_destroy(threadpool); 摧毀當(dāng)前線程池中所有任務(wù)。
int?thpool_num_threads_working(threadpool); 獲取當(dāng)前線程池中有多少正在工作的任務(wù)。
實(shí)現(xiàn)分析
1. 線程池初始化:thpool_init
該庫(kù)聲明了兩個(gè)全局變量:
keepalive表示線程池正在工作的標(biāo)志位,on_hold表示線程池掛起的標(biāo)志位。
所以初始化,第一步是設(shè)置兩個(gè)標(biāo)志位:
表示默認(rèn)創(chuàng)建的線程池的狀態(tài)應(yīng)該是工作保持工作狀態(tài)而不是先掛起。
然后申請(qǐng)線程池工作隊(duì)列所需的資源,并初始化每線程池屬性鎖。
最后,根據(jù)我們傳入的線程池的大小,申請(qǐng)對(duì)應(yīng)的線程資源:函數(shù):thread_init
線程初始化函數(shù)實(shí)現(xiàn)如下:
申請(qǐng)一個(gè)thread句柄,將thrad句柄賦值到thread數(shù)組中。

在初始化的過(guò)程中,我們需要改變線程數(shù)組中的內(nèi)容,所以需要給線程初始化函數(shù)中傳遞一個(gè)指向該變量的指針,而不是當(dāng)前變量。
2. 添加工作到線程池中:thpool_add_work
這個(gè)函數(shù)有三個(gè)參數(shù):thpool_*?thpool_p,?void?(*function_p)(void*),?void*?arg_p
指向線程池的指針
指向工作任務(wù)函數(shù)的函數(shù)指針
需要傳遞給工作任務(wù)的參數(shù)
函數(shù)實(shí)現(xiàn)流程如下:
3. 關(guān)鍵實(shí)現(xiàn) thread_do
該函數(shù)是線程池實(shí)現(xiàn)的關(guān)鍵,我們線程池中對(duì)于線程的執(zhí)行及調(diào)度,實(shí)現(xiàn)過(guò)程如下:
設(shè)置線程可以接收的信號(hào)量:prctl(PR_SET_NAME, thread_name);
獲取線程資源到當(dāng)前函數(shù)中:thpool_* thpool_p = thread_p->thpool_p;
下面是核心實(shí)現(xiàn)邏輯:
這個(gè)函數(shù)只是一個(gè)最簡(jiǎn)單最基本的調(diào)用方式,根據(jù)我們添加的順序來(lái)完成工作隊(duì)列中任務(wù)的執(zhí)行,在此基礎(chǔ)上,我們可以增加線程池中工作的優(yōu)先級(jí)、搶占的執(zhí)行機(jī)制,這樣對(duì)我們thread_do函數(shù)中的邏輯會(huì)產(chǎn)生比較大的邏輯變動(dòng),這個(gè)就由我們后面去進(jìn)行分析了。
示例分析
這個(gè)示例非常簡(jiǎn)單,結(jié)合上面的API說(shuō)明就可以看懂。
首先創(chuàng)建了一個(gè)4個(gè)線程的線程池,添加40個(gè)任務(wù)到線程池中,然后等待線程池執(zhí)行完畢,最后釋放線程池。