2016-03-03 24 views
0

我知道保護複雜數據結構的必要性。像鏈接列表和信號量一樣。我看到了當一個線程修改列表而另一個線程在列表中行走時會發生的不好的事情。是讀取/寫入布爾值所需的信號量

但是,這是一個非常簡單的數據字段所需要的,就像一個布爾值?在我工作的地方,我看到很多代碼,如下面的例子,或者需要代碼審查人員添加這些代碼。這真的需要嗎?如果是這樣,有人可以解釋如果沒有使用信號量會出現什麼問題嗎?

#define TRUE 1 
#define FALSE 0 
static int enabled; 

int is_foo_enabled(void) 
    { 
    int ret; 
    reserve_foo_semaphore(); 
    ret = enabled; 
    release_foo_semaphore(); 
    return ret; 
    } 

void enable_foo(void) 
    { 
    reserve_foo_semaphore(); 
    enabled = TRUE; 
    release_foo_semaphore(); 
    } 

void disable_foo(void) 
    { 
    reserve_foo_semaphore(); 
    enabled = FALSE; 
    release_foo_semaphore(); 
    } 
+1

'int'不是布爾類型。你可以使用'stdatomics.h'作爲一個輕量級的選擇。 – Olaf

+0

這取決於.................. –

回答

0

是它的需要,例如你的線程可以檢查此值,並且依賴於它是false之一,然後開始做一些事情,就像是false,但在此之前正確的,一些其他的線程它改變是真實的,而且這種行爲不再需要,甚至可能導致錯誤。此外,甚至改變布爾值也不是真正的原子操作,或者至少可能不是原子操作,所以當線程(或進程,如果我們談論共享內存)時,它會導致大混亂,例如同時更改此值。所以基本上,當代碼嘗試檢查或更改任何共享值(甚至是布爾值)時,您需要鎖定並釋放互斥鎖。同樣在你的問題的上下文中,即使它被用作布爾值,你也只有一個int,我不認爲任何人都認爲他不需要用於改變整數的mutext。

1

原子訪問,保證多件事情(取決於內存模型語義) -

  • 對於較大的數據大小(甚至POD)它保證了讀取或寫入操作都自動完成的,即使該值在不同的緩存拆分行甚至頁面。
  • 對於讀取 - 修改 - 寫入類型的操作,它保證了讀寫操作是以原子方式完成的,所以當另一個線程正在修改值時,沒有線程可能會讀取陳舊的數據。另一種看待這種情況的方式是,原子訪問保證CPU可以在讀取和寫入操作之前或之後對所有其他讀取/寫入進行排序,但不在它們之間。
  • 額外的保障可能會因您的內存模型(擊劍,序列化,等等。)

您將第一顆子彈不是適用於布爾類型(雖然這取決於你的系統是正確的,誰知道申請如何在那裏實現一個布爾值..),但其他保證仍然很重要。