比方說,我有以下代碼:C++內存排序一致性
void* p0 = nullptr;
void* p1 = alloc_some_data();
void f1() {
p0 = p1;
p1 = nullptr;
}
假設f1
上線1.運行是否有可能(離開代碼,因爲它是)另一個線程可能在某一時刻看到p0
和p1
作爲nullptr
(如果編譯器或硬件重新排序指令,比如第二次分配在第一次之前發生)?
我問這個的原因是因爲我想實現一個垃圾收集器,我想知道是否需要使用原子指令訪問GC線程中的指針(std::atomic
)。如果GC線程看到p0 == p1 == alloc_some_data()
則沒有問題,但如果GC線程看到p0 == p1 == nullptr
,則會出現問題,因爲它會將p1中以前的數據報告爲無法訪問,因爲它顯然是可訪問的。
從我的理解來看,跟蹤gc over ref counting的好處是避免鎖(以refs爲增量)。如果每個更新程序線程中的引用更新需要互斥鎖,那麼性能增益優先於ref計數?跟蹤gc方法然後像lock參數計數方法一樣使用鎖膨脹代碼路徑(在mutator線程中),對吧?是否可以編寫一個跟蹤gc,其中的增變器線程可以用一個簡單的MOV指令更新一個引用?任何人都可以指向一個方向(一篇文章或一本書...)嗎? –
我不太瞭解垃圾回收評論。就我個人而言,我喜歡引用計數,因爲內存儘快釋放。某些操作系統提供的原子增量和減量指令比使用互斥鎖要快得多。在這種情況下,引用計數會勝出。如果您使用的是Windows/Visual Studio,則可能需要查看Microsoft特定的「volatile」語義。 – paddy
@DaniloCarvalho:我對GC也不太熟悉,但很多非引用計數GC都是* stop-the-world * GC:環境將停止所有線程,執行GC(可能重定位對象和更新指針),然後讓所有線程繼續。 –