簡體   English   中英

無鎖緩沖器

[英]Lock-free buffer

在我的代碼中,我有一個緩沖區,我要向其中添加數據的代碼是:

bool push_string(file_buffer *cb, const char* message, const unsigned short msglen)
{
    unsigned int size = msglen;

    if(cb->head >= (cb->size - size))
    {
        size = cb->size - cb->head - 1;
    }

    if(size < 1) return false;

    char* dest = cb->head += size;

    memcpy(dest, message, size);

    return (size == msglen);
}

由於我從多個中斷中添加數據(它們可以互免),所以我想知道這段代碼是否是線程安全的? 我將“ cb-> head”標記為易失性,但是如果另一個中斷恰好在“ head”的增加與“ dest”的賦值之間免除,則可能會出錯。

如何改進此代碼以使其更安全?

編輯:也許我不應該使用術語“線程安全”,因為沒有並行運行的線程,只有中斷的可能性。

C99沒有線程的概念,因此也沒有線程節省的概念。 只有C11有。 在C99中,唯一可以中斷安全的數據類型是sig_atomic_t ,但顯然這也與線程無關。

通常,在嘗試同時訪問數據結構時完全是錯誤的, volatile根本不能保證您會收到明智的數據。 即使在C11中,也無法保證任何操作的原子性,因此,例如,您可能處於指針值的下半部分已被寫入而上半部分尚未被寫入的情況。 這可能會給您帶來完全虛假的結果。 由於這樣的事情可能僅在百萬或在特殊情況下(例如重負載)發生一次,因此可能導致很難跟蹤的錯誤。

不要那樣做

C11為您提供了處理此類問題的新工具,尤其是原子操作。 它尚未完全實現,但是許多編譯器已經具有可以幫助您的擴展。 我已經將其中一些包裝在P99宏程序包中,因此從今天起,使用某些編譯器,您可以開始使用這些功能。

考慮信號中斷信號...如果您確實需要:

您可以在push_string()中阻止所有相關信號。

另一個依賴於應用程序的可能性可能是將信號處理程序代碼移到主“線程”中(信號處理程序代碼僅生成“事件”,這些事件會喚醒執行的主線程)。 我沒有關於您的應用程序的足夠信息,無法確定這是一個不錯的選擇。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM