線程共享的環境包括:進程代碼段、進程的公有數據(利用這些共享的數據,線程很容易的實現相互之間的通訊)、進程打開的文件描述符、信號的處理器、進程的當前目錄和進程用戶ID與進程組ID。
1.線程ID
每個線程都有自己的線程ID,這個ID在本進程中是唯一的。進程用此來標
由於線程間是並發運行的,每個線程有自己不同的運行線索,當從一個線
堆棧是保證線程獨立運行所必須的。
線程函數可以調用函數,而被調用函數中又是可以層層嵌套的,所以線程
4.錯誤返回碼
由於同一個進程中有很多個線程在同時運行,可能某個線程進行系統調用
所以,不同的線程應該擁有自己的錯誤返回碼變量。
5.線程的信號屏蔽碼
由於每個線程所感興趣的信號不同,所以線程的信號屏蔽碼應該由線程自
6.線程的優先級
由於線程需要像進程那樣能夠被調度,那么就必須要有可供調度使用的參
數,這個參數就是線程的優先級。
涉及多線程程序涉及的時候經常會出現一些令人難以思議的事情,用堆和棧分配一個變量可能在以后的執行中產生意想不到的結果,而這個結果的表現就是內存的非法被訪問,導致內存的內容被更改。
理解這個現象的兩個基本概念是:在一個進程的線程共享堆區,而進程中的線程各自維持自己堆棧。
另一運行機制就是如果聲明一個成員變量如 char Name[200],隨着這段代碼調用的結束,Name在棧區的地址被釋放,而如果是 char * Name = new char[200]; 情況則完全不同,除非顯示調用delete否則 Name指向的地址不會被釋放。
在B中如果用棧區 即采用臨時變量的機制分配聲明V和堆區,而者的結果是不同的。如果用棧區,如果變量地址為Am1-Am2這么大,退出B調用時候這段地址被釋放,C函數可能將這段內存改寫;這樣當D執行的時候,從內存Am1-Am2中讀取的內容就是被改過的了。
而如果用New(堆)分配,則不會出現那樣的情況,因為沒有顯示對用delete並且堆對於線程共享,即2線程可以看到1線程在堆里分配的東西,所以不會發生誤寫。
這個問題是筆者在公司實習的時候發現的,因為當時剛剛涉及多線程程序設計,操作系統中如此簡單的話題困擾筆者很久,希望可以對初涉C++多線程的讀者 有所幫助! 2)如果兩個線程共享堆,而且都有可能執行內存分配和釋放操作,就必須進行同步保護,這個和C類,R類,T類沒有關系。你看到的例子兩個線程應該是使用各 自的堆。
在 windows 等平台上,不同線程缺省使用同一個堆,所以用 C 的 malloc (或者 windows 的 GlobalAlloc)分配內存的時候是使用了同步保護的。如果沒有同步保護,在兩個線程同時執行內存操作的時候會產生競爭條件,可能導致堆內內存管理 混亂。比如兩個線程分配了統一塊內存地址,空閑鏈表指針錯誤等。
Symbian 的線程一般使用獨立的堆空間。這樣每個線程可以直接在自己的堆里分配和釋放,可以減少同步所引入的開銷。當線程退出的時候,系統直接回收線程的堆空間,線程內沒有釋放的內存空間也不會造成進程內的內存泄漏。
但是兩個線程使用共用堆的時候,就必須用 critical section 或者 mutex 進行同步保護。否則程序崩潰是早晚的事。如果你的線程需要在共用堆上無規則的分配和釋放任何數量和類型的對象,可以定制一個自己的 allcator,在 allocator 內部使用同步保護。線程直接使用這個 allocator 分配內存就可以了。這相當於實現自己的 malloc,free。但是更建議你重新審查一下自己的系統,因為這種情況大多數是不必要的。經過良好的設計,線程的本地堆應該能夠滿足大多數對象的需 求。如果有某一類對象需要在共享堆上創建和共享,這種需求是比較合理的,可以在這個類的 new 和 delete 上實現共享保護。