2011-03-21 153 views
5

我想根據當前的標準和C++ 0x以及實際情況(通常來說,但在我的情況下使用gcc 4.5.1 )。C++線程安全摘要

對於STL容器,我的理解是,根據當前標準,不保證線程安全性。這是真的,但實際上它們對於單個作者,多讀者使用(在gcc和可能是最現代的編譯器)是線程安全的?這是由C++ 11保證的嗎?

POD類型呢?我知道這個標準沒有任何保證,但我被告知,在實踐中,所有人都是線程安全的閱讀和寫作。當然,即使像增量運算符這樣簡單的東西可能仍然需要同步,因爲可能有多個讀取和寫入。

我主要對答案感興趣,但答案背後的原因將被讚賞。

+1

在當前的C++標準中沒有「線程」或「線程安全」的概念。 – 2011-03-21 17:35:01

+1

關於這種線程安全性的問題,沒有任何關於「線程安全」的含義的說明基本上是不可能回答的。必讀:[你稱之爲「線程安全」的東西是什麼(http://blogs.msdn.com/b/ericlippert/archive/2009/10/19/what-is-this-thing-you-call-線程safe.aspx)。 – 2011-03-21 17:35:23

+0

@David:偉大的文章,謝謝:) – 2011-03-21 17:45:05

回答

1

目前的標準在任何方面都沒有提及線程。實際上,標準容器提供線程安全讀取,但需要同步寫入。

關於線程安全/共享,C++ 0x並沒有多少談論(關於線程安全/共享的容器),而是談論分配等。最後,雖然對象位於容器中,但您讀取/寫入數據,並且至少有一個線程可能會修改數據時必須同步,所以它的結果幾乎相同。

POD數據並沒有真正改變:修改需要同步作爲一般規則。通常有一些數據類型的子集通常是原子操作,但該子集的成員因平臺而異。它通常包括類型,直到分配「自然」對齊的硬件的本地字大小;還有其他問題可以提出更多問題。

+0

雖然C++ 0x引入了'std :: atomic',但它的名字我認爲這裏有一定程度的線程安全性。不是嗎? – 2011-03-21 17:49:43

+0

@Matthieu M .:是的,C++ 0x在原子操作和互斥體方面增加了很多。這些將使您可以輕鬆地同步對容器的訪問,但沒有一個容器會自動同步(至少在我記得的範圍內)。 – 2011-03-21 17:53:11

+0

我不認爲容器是同步的。我似乎記得保證讀取操作不會修改它們(這裏沒有Splay Tree),但這就是它。 – 2011-03-21 19:46:48

0

POD和標準定義類型沒有任何線程安全性。代碼用戶完全可以同步他們的線程以確保沒有什麼不好的事情發生。

在C++ 0x中,我沒有什麼想法;沒有真正檢查標準的這個領域。

6

您提到的所有內容都不是線程安全的,無論是通過標準還是實踐。

標準沒有要求線程安全的原因是線程安全帶來了固有成本。一般來說,C++試圖不給你你沒有要求的東西。如果你想要線程安全,那麼你必須自己構建它。即使在包含各種同步原語的C++ 0x中也是如此。

這些東西在實際中不是線程安全的原因各不相同。通常,STL容器不是線程安全的,因爲它們的每個基本更新操作都需要多個步驟才能完成。如果一個線程嘗試讀取或更新一個容器,而另一個線程正在更新它,則容器將處於不確定狀態,因此結果將不可預知。

在POD類型的情況下,讀取和寫入也可以採取多個步驟來完成。這個最簡單的例子是32位機器上的一個64位整數。至少需要兩條指令來讀取或設置值。再一次,這意味着如果一個線程在另一個線程正在更新它的過程中嘗試讀取或更新該值,結果將是不可預知的。

0

C語言和C++都沒有在語言中內置的併發原語(例如)java與synchronised。這是(我相信)故意 - 即使是在現代版本 - 也是爲了避免在不需要時的開銷。 Unix在早期不支持輕量級進程,所以線程主要是內核問題。

各種專有線程庫(例如Solaris線程)由供應商生產的,該行業最終標準化的pthread庫,最初與純粹的用戶空間的線程模型(阻塞調用等I/O將阻止所有線程)和後面內核線程支持。 Windows,OS/2和其他各種操作系統提供專有的線程功能。

C/C++被設計爲運行在可能有或沒有線程支持的系統上,並且運行效率高 - 因此線程支持是可選的額外功能。 C++的設計哲學之一是程序員不應該爲他們不使用的功能付費。在多核心機器的時代,人們可以爭論這種方法的優點,但假設'the entire world is a PC'已被認爲是現在幾十年來編寫可移植C代碼的一個主要缺陷。

最終結果是線程往往是特定於平臺的,儘管跨平臺線程庫確實存在。