網(wǎng)站開發(fā)采購合同模板下載b2b
線程運(yùn)行控制
?專欄內(nèi)容:
參天引擎內(nèi)核架構(gòu)
本專欄一起來聊聊參天引擎內(nèi)核架構(gòu),以及如何實(shí)現(xiàn)多機(jī)的數(shù)據(jù)庫節(jié)點(diǎn)的多讀多寫,與傳統(tǒng)主備,MPP的區(qū)別,技術(shù)難點(diǎn)的分析,數(shù)據(jù)元數(shù)據(jù)同步,多主節(jié)點(diǎn)的情況下對故障容災(zāi)的支持。手寫數(shù)據(jù)庫toadb
本專欄主要介紹如何從零開發(fā),開發(fā)的步驟,以及開發(fā)過程中的涉及的原理,遇到的問題等,讓大家能跟上并且可以一起開發(fā),讓每個(gè)需要的人成為參與者。
本專欄會定期更新,對應(yīng)的代碼也會定期更新,每個(gè)階段的代碼會打上tag,方便階段學(xué)習(xí)。
?開源貢獻(xiàn):
- toadb開源庫
個(gè)人主頁:我的主頁
管理社區(qū):開源數(shù)據(jù)庫
座右銘:天行健,君子以自強(qiáng)不息;地勢坤,君子以厚德載物.
文章目錄
- 線程運(yùn)行控制
- 前言
- 概述
- 線程控制方法概覽
- 暫停線程
- 喚醒線程
- 線程取消
- 線程取消 API
- 線程取消流程
- 線程取消的原理
- 線程取消點(diǎn)
- 取消點(diǎn)屬性
- 屬性設(shè)置API
- 參數(shù)說明
- 總結(jié)
- 結(jié)尾
前言
現(xiàn)代的CPU都是多core處理器,而且在intel處理器中每個(gè)core又可以多個(gè)processor,形成了多任務(wù)并行處理的硬件架構(gòu),在服務(wù)器端的處理器上架構(gòu)又有一些不同,傳統(tǒng)的采用SMP,也就是對稱的多任務(wù)處理架構(gòu),每個(gè)任務(wù)都可以對等的訪問所有內(nèi)存,外設(shè)等,而如今在ARM系列CPU上,多采用NUMA架構(gòu),它將CPU核分了幾個(gè)組,給每個(gè)組的CPU core分配了對應(yīng)的內(nèi)存和外設(shè),CPU訪問對應(yīng)的內(nèi)存和外設(shè)時(shí)速度最優(yōu),跨組訪問時(shí)性能會降底一些。
隨著硬件技術(shù)的持續(xù)發(fā)展,它們對一般應(yīng)用的性能優(yōu)化能力越來越強(qiáng),同時(shí)對于服務(wù)器軟件的開發(fā),提出更高要求,要想達(dá)到極高的并發(fā)和性能,就需要充分利用當(dāng)前硬件架構(gòu)的特點(diǎn),對它們進(jìn)行壓榨。那么,我們的應(yīng)用至少也是要采用多任務(wù)架構(gòu),不管是多線程還是多進(jìn)程的多任務(wù)架構(gòu),才可以充分利用硬件的資源,達(dá)到高效的處理能力。
當(dāng)然多任務(wù)框架的采用,不僅僅是多線程的執(zhí)行,需要對多任務(wù)下帶來的問題進(jìn)行處理,如任務(wù)執(zhí)行返回值獲取,任務(wù)間數(shù)據(jù)的傳遞,任務(wù)執(zhí)行次序的協(xié)調(diào);當(dāng)然也不是任務(wù)越多處理越快,要避免線程過多導(dǎo)致操作系統(tǒng)夯住,也要防止任務(wù)空轉(zhuǎn)過快導(dǎo)致CPU使用率飆高。
本專欄主要介紹使用多線程與多進(jìn)程模型,如何搭建多任務(wù)的應(yīng)用框架,同時(shí)對多任務(wù)下的數(shù)據(jù)通信,數(shù)據(jù)同步,任務(wù)控制,以及CPU core與任務(wù)綁定等相關(guān)知識的分享,讓大家在實(shí)際開發(fā)中輕松構(gòu)建自已的多任務(wù)程序。
概述
在多線程并發(fā)運(yùn)行過程中,總是會存在一些線程的調(diào)度管理,讓一些線程暫停,喚醒線程,取消運(yùn)行等,本文就來分享線程的控制方面的API,以及使用方法。
線程控制方法概覽
方法 | API | 描述 |
---|---|---|
暫停線程 | pthread_suspend_np pthread_suspend_all_np | 暫停一個(gè)指定的線程或所有線程 |
喚醒線程 | pthread_resume_np pthread_resume_all_np | 喚醒一個(gè)指定線程或所有線程 |
取消線程 | pthread_cancel | 讓指定線程結(jié)束運(yùn)行 |
創(chuàng)建線程取消點(diǎn) | pthread_testcancel | 線程只有在取消點(diǎn)時(shí)才會被取消 |
線程取消屬性設(shè)置 | pthread_setcancelstate pthread_setcanceltype | 取消屬性的設(shè)置 |
暫停線程
#include <pthread_np.h>int pthread_suspend_np(pthread_t tid);
void pthread_suspend_all_np(void);
讓指定線程或者其它所有線程掛起,這里調(diào)用者是不會被掛起的,如果指定掛起自己,則返回錯(cuò)誤。
掛起的線程,只有等待喚醒通知時(shí),才能繼續(xù)運(yùn)行。
喚醒線程
#include <pthread_np.h> int pthread_resume_np(pthread_t tid);
void pthread_resume_all_np(void);
喚醒指定線程,或者其它所有掛起的線程,當(dāng)指定的線程沒有掛起時(shí),不產(chǎn)生任何動作。
當(dāng)調(diào)用pthread_resume_all_np
后,會掃描所有活動的線程,對于掛起的線程進(jìn)行喚醒。
線程取消
線程取消,會讓被取消的線程結(jié)束運(yùn)行,線程退出。
線程取消 API
#include <pthread.h>
int pthread_cancel(pthread_t thread);
參數(shù)指定線程的標(biāo)識符,取消指定線程,這里也包括自已;
API被調(diào)用以后,會給被取消的線程發(fā)送取消請求,取消請求是否被執(zhí)行,取決于該線程是否有取消點(diǎn),同時(shí)取消點(diǎn)屬性設(shè)置為可以響應(yīng)取消請求。
線程取消流程
線程處理取消請求的流程流程如下:
- 接收處理清求
- 彈出清理回調(diào)函數(shù),并執(zhí)行
- 是否有線程本地?cái)?shù)據(jù)的銷毀函數(shù),如果有時(shí),則執(zhí)行
- 線程退出
此時(shí),如果線程是可連接的,則pthread_join需要被調(diào)用來回收資源。
線程取消的原理
線程取消的內(nèi)部是通過信號實(shí)現(xiàn),發(fā)送請求,實(shí)現(xiàn)是發(fā)送了一個(gè)信號;這就很好理解取消點(diǎn),它只是一個(gè)信號中斷處理點(diǎn)。
線程取消點(diǎn)
#include <pthread.h>
void pthread_testcancel(void);
調(diào)用此API可以在程序的調(diào)用位置創(chuàng)建取消點(diǎn),就是可以響應(yīng)線程的取消;有些代碼段,我們不希望被中斷,必須執(zhí)行或者不執(zhí)行,那么就可以在此代碼段的前后設(shè)置取消點(diǎn)。
一般線程中的取消點(diǎn)有以下幾種:
- 調(diào)用
pthread_testcancel
創(chuàng)建的取消點(diǎn); - 讓線程產(chǎn)生等待條件API,它們內(nèi)部會有取消點(diǎn),如信號量等待;
- 等待其它線程結(jié)束的調(diào)用,如
pthread_join
調(diào)用; - 信號等待sigwait
- 其它一些會阻塞線程的標(biāo)準(zhǔn)庫API,它們內(nèi)部會有取消點(diǎn),如sleep, read/write/send/recv等,在阻塞等待時(shí),此線程仍然可以被取消運(yùn)行。
取消點(diǎn)屬性
屬性設(shè)置API
#include <pthread.h>
int pthread_setcancelstate(int state, int *oldstate);
int pthread_setcanceltype(int type, int *oldtype);
參數(shù)說明
- state 取值,
- PTHREAD_CANCEL_ENABLE , 使能取消點(diǎn),也就是在此調(diào)用之后,如果設(shè)置了取消點(diǎn),它們就可以響應(yīng)取消請求;線程默認(rèn)情況下,取消點(diǎn)是使能的;
- PTHREAD_CANCEL_DISABLE, 禁用取消點(diǎn),也就是在此調(diào)用之后,如果設(shè)置了取消點(diǎn),它們不再響應(yīng)取消請求; 當(dāng)收到取消請求時(shí),它們會被阻塞,直到使用取消點(diǎn)后。
- type 取值
- PTHREAD_CANCEL_DEFERRED, 取消請求會被延遲處理;當(dāng)收到取消請求時(shí),不會立即處理,而是在下一個(gè)取消點(diǎn)時(shí)處理;
- PTHREAD_CANCEL_ASYNCHRONOUS, 立即處理取消請求,當(dāng)然操作系統(tǒng)不能保證實(shí)時(shí)性;
這兩個(gè)API都是設(shè)置當(dāng)前線程的取消點(diǎn)屬性。為什么會有這兩個(gè)函數(shù)呢? 因?yàn)樵谖覀兂绦蛑胁粌H用到了線程庫函數(shù),還有標(biāo)準(zhǔn)C庫函數(shù),還有其它,而線程庫的取消點(diǎn)我們可以自己設(shè)定,而其它庫函數(shù)的取消點(diǎn)只能通過這兩個(gè)函數(shù)來控制,是否需要啟用。
總結(jié)
本文分享了關(guān)于線程運(yùn)行、掛起、喚醒、取消運(yùn)行等控制操作以及相關(guān)API,體現(xiàn)出并發(fā)操作的復(fù)雜性,對于掛起或取消運(yùn)行要特別注意它們的時(shí)機(jī),避免產(chǎn)生意想不到的結(jié)果。
本文所涉及的代碼已經(jīng)上傳到工程hatchCode, 在multipleThreads/example_06目錄下;
結(jié)尾
非常感謝大家的支持,在瀏覽的同時(shí)別忘了留下您寶貴的評論,如果覺得值得鼓勵(lì),請點(diǎn)贊,收藏,我會更加努力!
作者郵箱:study@senllang.onaliyun.com
如有錯(cuò)誤或者疏漏歡迎指出,互相學(xué)習(xí)。