前面兩篇博客主要介紹了內存池的原理和實現,這篇博客主要是介紹如何優化多線程安全的內存池
內存池的實現和管理(二)中內存池的實現代碼存在的問題
雖然在內存申請和釋放的時候,使用lock_guard()實現了多線程安全的內存池,但是頻繁的加鎖和解鎖帶來了不必要的上下文切換開銷,導致整個內存池的使用性能下降許多(主要體現在單次申請釋放/釋放內存需要的時間上升),和直接向系統申請內存的效率差許多
也就是說,雖然可以減少內存碎片的產生,但是並不能提高申請內存的效率
優化方案一:
在多線程情況下,申請內存時加鎖是必然的,每次申請向內存池申請內存塊的時候都要即時加鎖,但是釋放內存塊的時候我們可以延時釋放,做一個定時任務去遍歷內存池中管理內存塊的鏈表,加鎖一次釋放多個內存塊,這樣就減少了釋放內存塊時的加鎖次數
在內存池中釋放內存塊有兩個步驟:
1、把內存使用標記從已使用狀態改為未使用
2、第一個未使用內存塊指針的移動
釋放內存時只要求第2步需要互斥進行,所以我們在釋放的時候先修改標記狀態(不加鎖),執行一次定時任務,遍歷管理內存塊的鏈表,修改第一個未分配內存塊的指針(加鎖)
優化方案二:
產生沖突的根本原因是因為多個線程共用一個內存池,我們可以讓每個線程都擁有一個內存池,這樣內存塊的申請和釋放都在本線程內進行,自然不用加鎖
但是這樣在多線程的 情況下使用不方便,內存利用率低下,並且管理內存池很繁瑣
換一個思路,依然時多個線程共用一個內存池,但是我們給不同的線程安排不同的內存使用區域,這樣即時不加鎖也可以實現內存池的互斥使用
具體做法是可以給num個內存塊進行編號,假設有n個線程,每個線程可使用的內存塊個數t=num/n,根據線程id確定該線程使用的內存區域為[t*(id-1),t*id);id的取值范圍為[1,n]
參考博客https://blog.csdn.net/luzubodfgs/article/details/65632609