久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

STL容器線程安全性

 看風(fēng)景D人 2014-09-01

條款12:對STL容器線程安全性的期待現(xiàn)實一些 
標(biāo)準(zhǔn)C++的世界是相當(dāng)保守和陳舊的。在這個純潔的世界,,所有可執(zhí)行文件都是靜態(tài)鏈接的,。不存在內(nèi)存映射文件和共享內(nèi)存。沒有窗口系統(tǒng),,沒有網(wǎng)絡(luò),,沒有數(shù)據(jù)庫,,沒有其他進程。在這種情況下,,當(dāng)發(fā)現(xiàn)標(biāo)準(zhǔn)沒有提到任何關(guān)于線程的東西時你不該感到驚訝,。你對STL的線程安全有的第一個想法應(yīng)該是它將因?qū)崿F(xiàn)而不同。 

當(dāng)然,,多線程程序是很普遍的,,所以大部分STL廠商努力使他們的實現(xiàn)在線程環(huán)境中可以正常工作。但是,,即使他們做得很好,,大部分負(fù)擔(dān)仍在你肩上,而理解為什么會這樣是很重要的,。STL廠商只能為你做一些可以減少你多線程的痛苦的事情,,你需要知道他們做了什么。 

STL容器(和大多數(shù)廠商的愿望)里對多線程支持的黃金規(guī)則已經(jīng)由SGI定義,,并且在它們的STL網(wǎng)站[21]上發(fā)布,。大體上說,你能從實現(xiàn)里確定的最多是下列內(nèi)容: 

多個讀取者是安全的,。多線程可能同時讀取一個容器的內(nèi)容,,這將正確地執(zhí)行。當(dāng)然,,在讀取時不能有任何寫入者操作這個容器,。 
對不同容器的多個寫入者是安全的。多線程可以同時寫不同的容器,。 
就這些了,,那么讓我解釋你可以期望的是什么,而不是你可以確定的,。有些實現(xiàn)提供這些保證,,但是有些不。 

寫多線程的代碼很難,,很多程序員希望STL實現(xiàn)是完全線程安全的,。如果是那樣,程序員可以不再需要自己做并行控制,。毫無疑問這將帶來很多方便,,但這也非常難實現(xiàn)。一個庫可能試圖以下列方式實現(xiàn)這樣完全線程安全的容器: 

在每次調(diào)用容器的成員函數(shù)期間都要鎖定該容器,。 
在每個容器返回的迭代器(例如通過調(diào)用beginend)的生存期之內(nèi)都要鎖定該容器,。 
在每個在容器上調(diào)用的算法執(zhí)行期間鎖定該容器。(這事實上沒有意義,,因為,,正如條款32所解釋的,,算法沒有辦法識別出它們正在操作的容器。不過,,我們將在這里檢驗這個選項,,因為它的教育意義在于看看為什么即使是可能的它也不能工作。)


-----------------------------------

現(xiàn)在考慮下列代碼,。它搜尋一個vector<int>中第一次出現(xiàn)5這個值的地方,,而且,如果它找到了,,就把這個值改為0,。

vector<int> v;
vector<int>::iterator first5(find(v.begin(), v.end(), 5)); // 行1
if (first5 != v.end()){ // 行2
*first5 = 0; // 行3
}

在多線程環(huán)境里,另一個線程可能在行1完成之后立刻修改v中的數(shù)據(jù),。如果是那樣,,行2對first5和v.end的檢測將是無意義的,因為v的值可 能和它們在行1結(jié)束時的值不同,。實際上,,這樣的檢測會產(chǎn)生未定義的結(jié)果,因為另一線程可能插在行1和行2之間,,使first5失效,,或許通過進行一次插入 操作造成vector重新分配它的內(nèi)在內(nèi)存。(那將使vector全部的迭代器失效,。關(guān)于重新分配行為的細(xì)節(jié),,參見條款14。)類似的,,行3中對*first5的賦值是不安全的,,因為另一個線程可能在行2和行3之間執(zhí)行,并以某種方式使first5失效,,可能通過刪除它指向(或至少曾經(jīng)指向)的元素,。

在上面列舉的鎖定方法都不能防止這些問題。行1中begin和end調(diào)用都返回得很快,,以至于不能提供任何幫助,,它們產(chǎn)生的迭代器只持續(xù)到這行的結(jié)束,而且find也在那行返回,。

要讓上面的代碼成為線程安全的,,v必須從行1到行3保持鎖定,很難想象STL實現(xiàn)怎么能自動推斷出這個,。記住同步原語(例如,,信號燈,互斥量,等 等)通常開銷很大,,更難想象實現(xiàn)怎么在程序沒有明顯性能損失的情況下做到前面所說的——以這樣的一種方式設(shè)計——讓最多一個線程在1-3行的過程中能訪問 v。

這樣的考慮解釋了為什么你不能期望任何STL實現(xiàn)讓你的線程悲痛消失,。取而代之的是,,你必須手工對付這些情況中的同步控制。 在這個例子里,,你可以像這樣做:

vector<int> v;
...
getMutexFor(v);
vector<int>::iterator first5(find(v.begin(), v.end(), 5));
if (first5 != v.end()) { // 這里現(xiàn)在安全了
*first5 = 0; // 這里也是
}
releaseMutexFor(v);

一個更面向?qū)ο蟮慕鉀Q方案是創(chuàng)建一個Lock類,,在它的構(gòu)造函數(shù)里獲得互斥量并在它的析構(gòu)函數(shù)里釋放它,這樣使getMutexFor和releaseMutexFor的調(diào)用不匹配的機會減到最小,。這樣的一個類(其實是一個類模板)基本是這樣的:

template<typename Container>    // 獲取和釋放容器的互斥量
class Lock { // 的類的模板核心,;
public: // 忽略了很多細(xì)節(jié)
Lock(const Containers container)
: c(container)
{
getMutexFor(c); // 在構(gòu)造函數(shù)獲取互斥量
}

~Lock()
{
releaseMutexFor(c); // 在析構(gòu)函數(shù)里釋放它
}

private:
const Container& c;
};

使用一個類(像Lock)來管理資源的生存期(例如互斥量)的辦法通常稱為資源獲得即初始化,你應(yīng)該能在任何全面的C++教材里讀到它,。一個好的開端是Stroustrup的《The C++ Programming Language》[7],, 因為Stroustrup普及了這個慣用法,但你也可以轉(zhuǎn)到《More Effective C++》的條款9,。不管你參考了什么來源,,記住上述Lock是被剝離到最原始的本質(zhì)的。一個工業(yè)強度的版本需要很多改進,,但是那樣的擴充與STL無關(guān),。而 且這個最小化的Lock已經(jīng)足夠看出我們可以怎么把它用于我們一直考慮的例子:

vector<int> v;
...
{ // 建立新塊;
Lock<vector<int> > lock(v); // 獲取互斥量
vector<int>::iterator first5(find(v.begin(), v.end(), 5));
if (first5 != v.end()) {
*first5 = 0;
}
} // 關(guān)閉塊,,自動
// 釋放互斥量

因為Lock對象在Lock的析構(gòu)函數(shù)里釋放容器的的互斥量,,所以在互斥量需要釋放是就銷毀Lock是很重要的。為了讓這件事發(fā)生,,我們建立一個里 面定義了Lock的新塊,,而且當(dāng)我們不再需要互斥量時就關(guān)閉那個塊。這聽上去像我們只是用關(guān)閉新塊的需要換取了調(diào)用releaseMutexFor的需 要,,但是這是錯誤的評價,。如果我們忘記為Lock建立一個新塊,互斥量一樣會釋放,,但是它可能發(fā)生得比它應(yīng)該的更晚——當(dāng)控制到達封閉塊的末端,。如果我們 忘記調(diào)用releaseMutexFor,我們將不會釋放互斥量,。

而且,,這種基于Lock的方法在有異常的情況下是穩(wěn)健的。C++保證如果拋出了異常,,局部對象就會被銷毀,,所以即使當(dāng)我們正在使用Lock對象時有 異常拋出,Lock也將釋放它的互斥量,。如果我們依賴手工調(diào)用getMutexFor和releaseMutexFor,,那么在調(diào)用 getMutexFor之后releaseMutexFor之前如果有異常拋出,,我們將不會釋放互斥量。

異常和資源管理是重要的,,但是它們不是本條款的主題,。本條款是關(guān)于STL里的線程安全。當(dāng)涉及到線程安全和STL容器時,,你可以確定庫實現(xiàn)允許在一個容器上的多讀取者和不同容器上的多寫入者,。你不能希望庫消除對手工并行控制的需要,而且你完全不能依賴于任何線程支持,。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多