設計一個程序,要考慮如何分配和管理內存,以下是對所有內存分配和管理類型的總結。
第一、進程級的內存資源,也叫全局靜態內存,其生命周期是伴隨整個進程的運行期間,可以用作在進程范圍內共享數據的方法。對應于C語言的全局靜態變量,如 static int buf[10];
在多線程的情況下,假如每個線程并行運行時都會使用某個全局靜態變量,而又不希望受到其它線程的干擾,于是就產生了第二種線程級的內存資源。
第二、線程級的內存資源,其生命周期是伴隨一個線程的始末,每創建一個新的線程,這種類型的內存資源就會被創建一次,線程結束時,它也被銷毀。對應于C語言的線程級全局變量,如
static __thread int buf[MAX_ERROR_LEN];
第一種和第二種內存都存在的問題是,如果它們在整個進程或者線程的生命周期中被使用的頻率很低,但是卻占用了大量的內存,在線程的創建和結束時需要消耗較大的分配和銷毀工作量,那就不是很理想,針對內存需求量較大、使用頻率又較低的情況,產生了第三種內存。
第三、共享內存池,就是在進程的范圍內或者是整個操作系統的范圍內先分配一定數量的全局內存塊,供所有的線程共享使用,線程需要的時候申請一塊來用,結束以后將它歸還共享池。這跟線程使用malloc動態申請一塊內存有什么區別呢?區別在于,malloc分配的是固定數量的內存,而我們需要的內存往往是不確定的,不知道需要多少內存,我們需要一個動態的內存管理器,這通常是我們自己設計的一個內存管理器,比如我在上篇文章中設計的MemChain,共享內存池中就是這樣的動態內存分配管理器,能滿足任意數量內存的需求,不再需要我們額外考慮內存的分配。創建和銷毀一個MemChain往往要比申請一個已有的MemChain更耗時,所以我們采用共享池,而不是在線程中頻繁創建和銷毀MemChain.
還有最后兩種,就是我們最常用的棧內存和堆內存。
第四、棧內存,棧是一種線程內函數級的內存資源,其生命周期是一個函數的一次運行的始末,它的大小受到操作系統的限制,比如Ubuntu默認的棧容量是8M,我們在函數中使用的自動變量的總和不能超過棧的容量,因此,函數中使用的自動變量都是比較少量的內存,需要大內存時就需要從堆中獲取。
第五、堆內存,堆內存是不受任何限制的,系統有多少就可以用多少,直到耗盡內存為止,第三種內存就屬于堆內存,只是我們設計了一個共享池的機制來預先加載一部分堆內存,并用MemChain方便的管理和使用它。