2013-11-20 129 views
0

我有兩個線程,稱它們爲服務器線程和計算線程。服務器線程啓動計算線程,向它傳遞一個指向布爾變量「停止標誌」的指針。當服務器線程將stop標誌設置爲true時,計算線程應退出其計算循環並從run函數返回。在線程之間共享不帶鎖的線程值C

我的問題是,有沒有什麼辦法安全地共享標誌兩個線程之間而沒有使用任何鎖(互斥,信號等)?請記住:

  • 標誌將被設置爲true,一旦
  • 標誌決不會被設置回一次設置爲true
  • 假的,只有一個服務器線程,並且只有一個計算線程

在這種情況下,我將「安全地」定義爲在服務器線程中將標誌設置爲true的任何方法都是保證在合理的時間內在計算線程中反映真實值的。 (如果你的答案包括「最終」一詞,它可能不符合「合理的時間」)。

我對便攜式和非便攜式解決方案都很感興趣。我在一個Linux平臺上運行,但除此之外還有一些靈活性:GCC,Clang,內核版本,C標準版本等。

+0

合理的時間量取決於計算循環的內容。 – StoryTeller

回答

2

聲明標誌(您的bool)爲volatile就足夠了。這只是禁用該變量的緩存,每次讀取都會保證返回當前值。

3

在這種情況下,將變量定義爲volatile就足夠了。

通過單次寫入,腐敗是不可能的。

無法保證寫入的時間可見,但您不需要一次。

volatile可防止有害的優化 - 如果編譯器發現變量沒有被修改,它可能會認爲它不需要從內存中重新讀取它。 volatile可以防止這種情況發生。

+0

不,您還必須向編譯器說明它必須*在內存中備份變量。 –

+0

@JensGustedt,'volatile'這樣做。 – ugoren

+0

我不明白'volatile'在哪裏。 'register'和'volatile'並不矛盾,編譯器有權不備份內存中的volatile變量。 「volatile」抑制的唯一情況是關於變量值的某些假設。 –

1

用於該目的的正確數據類型是新類型atomic_flag以及最近C標準C11的附帶功能。大多數編譯器還沒有,但有類似的東西,你可以用它來模擬這個。爲了同樣的目的,例如gcc和親屬有__sync_lock_test_and_set__sync_lock_release

只要聲明一個變量volatile像別人所說的那樣是而不是一般就足夠了。儘管很少出現int_Bool,但如果位於緩存邊界之間,則對此類變量的讀取或寫入可能是部分的。例如,這可能導致變量的更高位被設置(導致解釋爲true)。

/* in file scope */ 
int work_has_been_initiated = 0; 


/* inside the threads */ 
if (!__sync_lock_test_and_set(&work_has_been_initiated, 1)) { 
    /* do the work, here */ 
} 

如果思邁特是不是你的目的夠強,你可以使用其他的原子操作,如__sync_bool_compare_and_swap

+0

您可以使用__sync_lock_test_and_set和__sync_lock_release舉個例子嗎? – brooks94

+0

@ brooks94,請參閱我的編輯 –

+0

這是一個矯枉過正的行爲 - 如果只有一個線程修改標誌,它不需要原子操作。雖然我承認有時過度使用會更好,但如果代碼變得更復雜,並且沒有人更新同步。 – ugoren