1. 程式人生 > >同一程序中的執行緒究竟共享哪些資源

同一程序中的執行緒究竟共享哪些資源

執行緒共享的環境包括:程序程式碼段、程序的公有資料(利用這些共享的資料,執行緒很容易的實現相互之間的通訊)、程序開啟的檔案描述符、訊號的處理器、程序的當前目錄和程序使用者ID與程序組ID。

    程序擁有這許多共性的同時,還擁有自己的個性。有了這些個性,執行緒才能實現併發性。這些個性包括:
    1.執行緒ID
      每個執行緒都有自己的執行緒ID,這個ID在本程序中是唯一的。程序用此來標識執行緒。     2.暫存器組的值
       由於執行緒間是併發執行的,每個執行緒有自己不同的執行線索,當從一個線程切換到另一個執行緒上時,必須將原有的執行緒的暫存器集合的狀態儲存,以便
   將來該執行緒在被重新切換到時能得以恢復。     3.執行緒的堆疊        堆疊是保證執行緒獨立執行所必須的。執行緒函式可以呼叫函式,而被呼叫函式中又是可以層層巢狀的,所以執行緒 必須擁有自己的函式堆疊,使得函式呼叫可以正常執行,不受其他執行緒的影響。
    4.錯誤返回碼
       由於同一個程序中有很多個執行緒在同時執行,可能某個執行緒進行系統呼叫後設置了errno值,而在該執行緒還沒有處理這個錯誤,另外一個執行緒就在此時    被排程器投入執行,這樣錯誤值就有可能被修改。
       所以,不同的執行緒應該擁有自己的錯誤返回碼變數。
    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 上實現共享保護。

轉自:http://laiyuanyuan7.blog.163.com/blog/static/15274321201241191321666