2017-04-12 79 views
0

我有一個我個人實現的數據結構,現在需要跨多個線程使用。C - 如何使我的數據結構實現同步?

typedef struct 
{ 
    void** array_of_elements; 
    size_t size; 
} myStruct; 

爲簡單起見,假設我的數據結構具有以下功能:

// Gets a data element from the structure. 
void* get(myStruct *x); 
// Prints out all the data elements. 
void print(myStruct *x); 
// Adds an element into the structure. 
void add(myStruct *x, void *to_be_added); 

這是不以任何形式叫get,而另一個線程正在調用print因爲他們是兩個訪問的問題。但是,getprint無法正常工作,而add正在調用中。反之亦然,add不能工作,如果getprint目前正在進行中。

因此,我改變myStruct看起來像下面這樣:

typedef struct 
{ 
    void** array_of_elements; 
    size_t size; 

    // True when a mutator is editing this struct. 
    bool mutating; 
    // The number of threads currently accessing this struct. 
    int accessors; 
} myStruct; 

現在我的功能如下所示:

void* get(myStruct *x) 
{ 
    // Wait for mutating to end. 
    while (x->mutating); 
    // Indicate that another accessor is now using this struct. 
    x->accessors++; 

    // get algorithm goes here 

    // Declare we are finished reading. 
    x->accessors--; 

    return ... 
} 

// Same as above... 
void print(myStruct *x) 
... 

void add(myStruct *x) 
{ 
    // Wait for any accessors or mutators to finish. 
    while (x->mutating || x->accessors > 0);  
    x->mutating = true; 

    // add algorithm here 

    x->mutating = false; 
} 

,我覺得有很多的問題,這的方法,我找不到解決方法:

  • 我的一位同學告訴我,使用while循環會減慢線程的速度。
  • 它沒有排隊感。開始等待myStruct完成使用的第一種方法不一定是接下來的方法。
  • 即使如果我有一個隊列數據結構的線程去下,數據結構也需要同步,這本身是一個無限循環需要一個同步數據結構來同步自己
  • 我認爲可能在相同的納秒中,一個線程將accessors計數器從0更改爲1(這意味着它們要開始讀取),但是可能突變線程看到它的值爲0並開始變異。然後,mutator線程和訪問器線程將同時進行。
  • 我敢肯定,這個邏輯可能會導致網格鎖定(線程無限等待)。
  • 我不知道如何使某些線程在需要執行此任務時能夠睡眠並喚醒,除了它被卡在while循環中。
+0

研究讀寫鎖... – Dmitri

+0

@Dmitri我讀寫鎖的程度如何,甚至不會遠遠接近實際實現的樣子? – Hatefiend

+0

如果你在線程之間共享一個變量,你應該使用原子訪問或者像互斥體那樣的某種同步機制。讀寫鎖就像一個互斥鎖,只是它允許多個線程讀取,但需要獨佔訪問才能寫入。對於posix線程,有'pthread_rwlock_t',並且windows有「slim reader writer locks」 – Dmitri

回答

0

你有正確的想法,只是錯誤的方法。我不確定你正在編寫什麼操作系統,但是你想看看mutexsemaphore的概念來做你想做的事情。

在Linux/Unix是POSIX兼容的,你可以看看並行線程:

http://www.cs.wm.edu/wmpthreads.html

在Windows上,你可以看看Critical Sections的東西接近mutex概念:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs.85).aspx

WaitForMultipleObjects用於接近某個東西semaphore

https://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v=vs.85).aspx

而且,是的,使用while循環是一個壞主意。在這種情況下,您正在使用所謂的繁忙循環。在這裏就可以了更多閱讀:

What is a busy loop?

使用mutexsemaphore,沒有while循環是必需的。祝你好運!

+0

那麼實現是依賴於庫的?這看起來不正確。我想我的'結構'裏面,我需要添加一些變量來鎖定我的線程,因爲我的'struct' **是互斥體**? – Hatefiend

+0

讓我重申一下:有沒有辦法在不使用任何線程庫的情況下執行此操作?使用我的結構的開發人員可能不在我設計的操作系統上。相反,我可以在我的'struct'中只是有一個變量來指示何時使用'struct'或不安全嗎? – Hatefiend

+0

@Hatefiend如果你不想把你的代碼綁定到任何特定的線程API,最好把鎖定保留給用戶,而不是試圖實現你自己的一次性互斥或讀寫鎖定(可能會比你期望的更難以正確執行)。他們所需要做的就是在調用訪問函數之前/之後獲取/釋放他們選擇的鎖(可能是與他們使用的任何線程實現一起使用的鎖)。 – Dmitri