2012-07-27 10 views
0

我在我的代碼中有幾個地方創建一個函數靜態對象,然後在調用該函數時使用(複製)。其中一個函數可以從任何線程調用。該函數不訪問除此靜態對象之外的任何共享狀態。競態條件:一個線程創建靜態對象,另一個線程在完成初始化之前使用它。如何處理?

當線程1第一次調用該函數時,該對象被創建並初始化。然而,(幸運的是)我有一個可重複的情況,程序切換到線程2並在初始化完成之前調用相同的函數。該對象被分配並使用了不良數據!

我不知道該如何處理。我在初始化代碼中使用了關鍵部分,但這甚至不是問題。這個對象在被初始化之前被使用。

我試圖讓這個線程本地使用__declspec(線程),但這顯然不適用於對象。

我可以用一個關鍵部分來包圍整個事物,也許這是最好的解決方案,但是我擔心在代碼的其他部分出現這樣的問題 - 有一個普通的解。

+1

從MSVC切換到英特爾後,我遇到過類似的問題。我們的解決方案是在可能的情況下移除統計信息,並在所有其他類庫中確保首次訪問包含靜態變量的函數被封裝在關鍵部分中。請注意,變量的構造函數是靜態的是不夠的,但對函數的訪問 - 導致變量的初始化 - 必須是原子的。顯然這導致了某種類型的代碼氣味,因爲你必須確保函數的每個「第一次調用」都是原子的... – MFH 2012-07-27 21:38:11

回答

2

如果你在Windows上,你可以使用InitOnceExecuteOnce API。更多細節可在this Raymond Chen發佈。也看看更通用的std::call_once

+1

這個東西實際上是標準的,被稱爲'std :: call_once' – inf 2012-07-27 21:46:44

+0

Thanks @bamboon added it到我的答案。 – ThirdOne 2012-07-27 21:49:05

1

難道你不能在對象上使用信號量,當對象被創建時將信號量設置爲1,然後當對象被初始化(並準備使用)時將其遞減爲零。

雖然需要注意資源匱乏。

相關問題