線程基礎之JAVA和C++0x的特性
JAVA特性
JAVA線程通常是一個帶有run()方法的java.lang.Thread的子類,然後調用這個子類對象的start()方法。我們之前定義過,數據競爭是因為兩個線程同時訪問內存單元,在JAVA中,內存單元是一個對象字段或數組元素。
由於JAVA旨在支持運行不受信任代碼作為受信任的應用程序的一部分,必須限製不受信任代碼的數據爭用造成的破壞。因此不允許數據爭用的任意行為,所以,JAVA語言規範包含了一個複雜的規則集,用來定義線程間的共享對象的行為,包括數據爭用的行為,這些規則的影響甚至專家都覺得驚訝。然而這些規則保證了免除數據爭用的程序的連續一致,對於程序來講是個更加容易的模型。
如上所述JAVA的數據爭用定義的可替換的定義是,並發衝突操作必須被阻止同時出現通過執行相同的線程,或者引入強製實施線程間的順序的同步變量。如果采用了這些機製,就可以說一個內存操作發生在另一個內存操作之前。因此不會發生交叉存儲。這基本相當於我們的定義。
在幾乎所有情況下,Java程序應該避免數據競爭,和依賴順序一致性。事實上附加的保障數據競爭問題隻有三種情況:
1.對於編譯器,必須保護它們。
2.對於尤其安全的敏感的代碼,作者需要限製不受信任的“沙箱”代碼引起的破壞。
3.對於極其性能敏感代碼的富有經驗的作者來講,使用同步變量的格外代價太高。盡管這樣的代碼存在於java.util.concurrent類庫裏,我們還是期望比較少的程序員寫這樣的代碼。
JAVA提供了不同尋常方式的鎖:每個JAVA對象都可以作為一個鎖。即邏輯上有個關聯鎖,而不是提供一個顯式的lock()和unlock()函數。JAVA提供了同步塊來獲得和釋放鎖。在指定的代碼塊被執行期間一直保持住鎖。
1 |
synchronized (object_used_as_lock) {
|
2 |
<i>code to be executed with lock held</i>
|
3 |
}
|
盡管最近JAVA版本提供了顯式鎖操作(java.util.concurent.locks),同步鎖有實質性的好處,鎖可以沿著代碼塊的方向釋放,其中包括異常被拋出,從而消除錯誤的常見來源。
正如我們上麵提及的,同步變量或者更正確的對象字段,通常用volatile關鍵字聲明。由於不是一個單獨的類型,可能有些令人驚訝,結果是:
數組元素不能同步,因為沒有辦法吧數組元素聲明為volatile。
正如我們前麵暗示的,volatile僅僅影響個別的內存存儲,如果i被聲明為volatile int i,那麼++i包含兩個單獨的不可分割的內存訪問,即增量作為一個不可分割的整體。
Java.util.concurrent.atomic包提供了一些原子類型規避這兩種結果。
Java.util.concurrent提供了許多其他的措施支持多線程,包括豐富的類庫用來同步或線程間的交互。
一些C++0x 特征
約定成俗,我們要用術語c++0x指下一個c++標準,盡管我們並不期望它被正式作為一個ISO標準直到2010或2011年。一個委員會起草的標準目前是可用的,並且我們期望許多供應商支持早於2011年的部分,在這我們所有的解釋明確地適應2008委員會草案。
和當前(2003)C++標準不同,C++0X明確的支持線程,線程通過std::thread類的實例創建,調用構造函數或者執行可調用的對象。
由於C++沒有被設計來提供保護不受信任的代碼的,它無法保證數據爭用,允許數據爭用的任意程序產生”未定義行為”。
數據爭用比較少的時候,提供的一些低層次的類庫措施不能用來提供連續一致性。正像JAVA,這顯而易見不是官方語言描述,在這種情況下,不使用數據爭用而用低層次類庫措施的語言描述更為複雜。
可以通過構造互斥獲得鎖,典型的是std::mutex,然後通過它獲得構造函數std::lock_quard對象,確保在lock_quard析構函數釋放鎖,正如JAVA中被釋放,即使是拋出異常。因此看起來像典型的代碼來獲得一個鎖。
#include <mutex>
std::mutex mtx; // The lock; shared by multiple threads
…
{std::lock_guard _(mtx);
++c;
}
在c++0x中,整形同步變量i可能被聲明為atomic<int> i;
同步變量與普通變量不同有個不同的類型,因此可以提供成員函數的不同實現,如果i像以上一樣被聲明,並發訪問確保了正如以前一樣的連續一致的行為,但是也確保了一個不可分割的操作,++i自動增加。
(C++裏也有Volatile,由於曆史原因,這意味著別的。)
目前看來,c++0x模型將在其他環境中,目前跡象表明,下一個C標準將遵循一種方法類似c++0x。OpenMP似乎也正走向一個類似解決方案。
最後更新:2017-05-23 15:36:53