天天看點

并發模式&&線程特定存儲

5.5線程特定的存儲器(Thread-Specific Storage)

1.問題 

      為了避免競争條件、資源耗盡和死鎖多線程應用程式需要複雜的并發控制協定,進而難以程式設計。由于存在加鎖開銷,是以多線程應用程式的性能往往比不上單線程應用程式,事實上它們的性能可能更糟,特别是在多處理平台上。在并發程式中有兩個強制條件:

      1)多線程應用程式應既容易程式設計又高效。特别地,對邏輯上全局的但實體上局限于一個線程的資料的通路應是原子的,且不會導緻對每次通路的加鎖開銷。

      2)許多遺産庫和應用程式最初是在單一控制線程的假定下編寫的。是以它們常常在方法間通過諸如errno的全局對象隐式地傳遞資料,而不是顯式地傳遞參數。将這些代碼轉移到多線程中運作時,通常不太可能改變遺産應用程式中現存的接口和代碼。

2.解決方案

      為每個針對具體線程的對象引入一個全局通路點,但是在每個線程的存儲器中儲存“真實”的對象。應用程式僅通過它們的全局通路點管理這些線程特定對象。

3.結構

      線程特定對象是一個隻能由特定線程通路的對象執行個體。

并發模式&&線程特定存儲

      線程使用一個由關鍵字工廠配置設定的關鍵字來辨別一個線程特定對象。由關鍵字工廠生成的關鍵字有一個取值範圍,以確定每個線程特定對象在“邏輯上”是全局的。

并發模式&&線程特定存儲

      一個線程特定對象包含與特定線程關聯的線程特定對象的集合。每個線程有自己的線程特定對象集。線上程特定對象集内部定義了一對方法,set()和get(),将全局管理的關鍵字集合映射到集合中存儲的線程特定對象。通過向get()傳遞一個辨別對象的關鍵字作為參數,線程特定對象集的用戶端可以獲得一個指向某一線程特定對象的指針。客戶機可以通過由get()方法傳回的指針檢查或修改對象。類似地,客戶機可以通過将對象指針以及相關的關鍵字以參數形式傳遞給set()來向對象集添加一個指向線程特定對象的指針。

并發模式&&線程特定存儲

      可以定義一個線程特定對象代理,使客戶機像通路普通對象一樣通路一個特定類型的線程特定對象。如果不使用代理,那麼客戶機必須直接通路線程特定對象集并顯式地使用關鍵字,這樣做單調乏味并且易出錯。每個代理執行個體存儲一個惟一區分線程特定對象的關鍵字,這樣,每個關鍵字和每個線程都對應一個線程特定對象。

      線程特定對象代理與相關的線程特定對象的接口一緻。在内部,代理的接口方法首先使用由線程特定對象集提供的set()和get()方法,獲得一個由被存儲在代理中的關鍵字指定的指向線程特定對象的指針。在指針被獲得後,代理将最初的方法調用委托給它。

      應用程式線程是客戶機,它使用線程特定對象代理通路駐留線上程特定的存儲器中的線程特定對象。對于應用程式線程而言,當對一個線程特定對象進行實際方法調用時,該方法看上去好像是在對一個普通對象進行調用。多應用線程可以使用相同的線程特定對象代理通路它們惟一的線程特定對象。代理使用調用它的接口方法的應用線程的辨別符,來區分它所封裝的線程特定對象。

并發模式&&線程特定存儲

4.實作

1)實作線程特定對象集。

  1.1)确定線程特定對象的類型。

  1.2)确定将線程特定對象集存儲在何處。每個線程特定對象集既可以存儲在所有線程外也可以存儲線上程内:

    ·在所有線程外部。該政策将每個應用程式線程的辨別符映射為一個存儲在所有線程外部的全局線程特定對象集表。注意,應用程式線程可以通過調用線程庫中的API函數獲得它自身的線程辨別符。是以,外部線程特定對象集的實作可以容易地确定哪個線程特定對象集與指定應用程式線程相關聯。

     取決于外部表政策的不同實作,線程可以通路其他線程中的線程特定對象集。如果線程特定的存儲器實作可以在不再需要關鍵字時回收它們。這也許是有用的,因為全局表有助于由“清除”線程通路所有線程特定對象集以删除對應于被回收關鍵字的條目,關鍵字的回收對于僅支援有限數量關鍵字的線程特定的存儲器模式實作特别有用。

     将線程特定對象集存儲線上程外部的全局跟中的缺點是,增加了通路每個線程特定對象的開銷。該開銷是由每次修改包含所有線程特定對象集的全局表時,為避免競争條件而使用的同步機制所引起的。特别地,當關鍵字工廠建立一個新關鍵字時,需要進行串行化,因為其他應用程式線程可能在并發地建立關鍵字。然而,在相應線程特定對象集被确定後,應用程式線程不需要進行任何加鎖操作就可以通路集合中的線程特定對象。

    ·在每個線程内部。這種政策要求每個線程連同它的其他内部狀态,如它的運作時線程棧、程式計數器、通用寄存器和線程辨別符,一同存儲線上程特定對象集中。當線程通路一個線程特定對象時,使用相應的關鍵字作為到線程内部的線程特定對象集的索引,進而擷取該對象。和上述外部政策不同,當線程特定對象集存儲在每個線程内部時,不需要進行串行化。在這種情況下,所有對線程内部狀态的通路都發生線上程内部。

     然而,雖然不同消耗更多的總記憶體,但在每個線程本地存儲線程特定對象集時每個線程需要更多狀态。隻要大小的增長不會導緻線程建立,語境切換或銷毀的開銷的顯著增長,線程特定對象的内部政策就比外部政策更有效。

  1.3)定義一個将應用程式線程辨別符映射到線程特定對象集的資料結構。

  1.4)定義線上程特定對象集中将關鍵字映射到線程特定對象的資料結構。

  1.5)定義關鍵字工廠。

  1.6)定義從線程特定對象集存儲和獲得線程特定對象的方法。

2)實作線程特定對象代理。線程特定的存儲器模式定義了一個線程特定對象代理。每個代理應用代理模式定義一個對象作為線程特定對象的“代理”。在代理上調用方法的應用線程看起來,就像是通路一個普通對象,而實際上代理将方法傳遞給線程特定對象。該設計防止應用程式了解線程特定的存儲器的使用時間和方式。它也允許應用程式使用高層的、類型安全的以及平台無關的包裝器外觀通路由低層C函數API管理的線程特定對象。

  2.1)定義線程特定對象代理接口。對于線程特定對象,有兩個設計代理接口的政策,多态和參數化類型。

  2.2)實作線程特定對象代理的建立和析構。不論是應用多态還是參數化類型政策定義線程特定對象代理,都必須對線程特定對象代理的建立和析構進行管理。一般來說,代理的構造函數内部并不配置設定關鍵字或新的線程特定對象執行個體,有兩個原因:

    ·線程特定的存儲器語義。不同于使用代理的線程,線程特定對象代理通常由一個線程(例如應用程式的主線程)來建立。是以,在構造函數中,預初始化一個新的線程特定對象并不能獲得什麼好處,因為該執行個體隻能由建立它的線程通路。

    ·延遲建立。在某些作業系統中,關鍵字資源是有限的,而且應該直到絕對需要時才被配置設定。關鍵字的建立是以應當延遲,直到代理方法第一次調用。

     線程特定對象代理的析構函數提供了幾個富有技巧的設計。“顯而易見的”解決方案是釋放由關鍵字工廠配置設定的關鍵字。然而,該方法有幾個問題:

    ·不可移植性。很難編寫一個可移植的釋放關鍵字的代理析構函數。例如,Solaris線程(與Win32和POSIX Pthreads不同)沒有釋放不需要的關鍵字的API。

    ·競争條件。Solaris線程不提供釋放關鍵字的API的原因是它很難有效和正确地實作。問題在于每個線程都保持關鍵字所引用對象的獨立的拷貝。隻有所有線程都退出,并且記憶體被回收後才能安全地釋放一個關鍵字。 

  2.3)實作對線程特定對象的通路。

     使用多态政策時,具體代理的接口必須包括所有該類中線程特定對象提供的方法。具體代理的方法實作通常執行如下四個步驟:

    ·如果還沒有建立這種線程特定對象的話,建立一個新關鍵字。必須防止多線程為同一個TYPE的線程特定對象同時建立新關鍵字,并是以可以避免競争條件。可以通過應用雙檢查加鎖優化模式解決該問題。

    ·下一步,方法必須使用由代理存儲的關鍵字,以通過線程特定對象集獲得線程特定對象。

    ·如果對象還不存在,則“按需”建立該對象。

    ·所請求的操作被轉發到線程特定對象,所有操作結果都被傳回給客戶機應用線程。

     使用參數化類型執行個體化一個一般代理時,可以使用智能指針和擴充接口模式政策,實作通路任何線程特定對象方法的通用機制,和多态政策一樣,通用通路機制必須遵循上述實作步驟。

5.結論

優點:

1)高效。可以實作線程特定的存儲器模式,使得通路線程特定的資料時不需要加鎖。

2)可重用性。通過應用包裝器外觀模式,并将可重用的線程特定的存儲器模式代碼與應用程式特定的類相分離,可以使開發者避免考慮複雜并且不可移植的線程特定的關鍵字的建立和配置設定邏輯。

3)易用性。

4)可移植性。

不足:

1)它鼓勵對(線程特定的)全局對象的使用。許多應用程式不需要多線程通過公共通路點通路線程特定的資料。在這種情況下,應該存儲資料以便隻有擁有資料的線程才能通路它。

2)它使系統結構變得模糊。線程特定的存儲器的使用由于模糊了元件間的關系,是以可能使應用程式更難了解。

3)它限制了實作方式的選擇。 

http代理伺服器(3-4-7層代理)-網絡事件庫公共元件、核心kernel驅動 攝像頭驅動 tcpip網絡協定棧、netfilter、bridge 好像看過!!!!

但行好事 莫問前程

--身高體重180的胖子