2009-10-06 124 views
0

我是一箇中級程序員,但相對多線程的新手。 目前,我正在用類似下面這樣的結構的應用程序:線程安全訪問對象之間共享的數據

class Client 
{ 
    public: 
     Client(); 

    private: 
    // These are all initialised/populated in the constrcutor. 
     std::vector<struct clientInfo> otherClientsInfo; 
     ClientUI* clientUI; 
     ClientConnector* clientConnector; 
} 

class ClientUI 
{ 
    public: 
     ClientUI(std::vector<struct clientInfo>* clientsInfo); 

    private: 
     // Callback which gets new client information 
     // from a server and pushes it into the otherClientsInfo vector. 
     synchClientInfo(); 
     std::vector<struct clientInfo>* otherClientsInfo; 
} 

class ClientConnector 
{ 
    public: 
     ClientConnector(std::vector<struct clientInfo>* clientsInfo); 

    private: 
     connectToClients(); 
     std::vector<struct clientInfo>* otherClientsInfo; 
} 

有點一個人爲的例子,我知道了。程序流程是這樣的:

  • 客戶端被構造和填充otherClientsInfo並構造clientUI和clientConnector的指針otherClientsInfo。

  • 客戶端隨時調用synchClientInfo()服務器與新客戶端信息進行聯繫,解析新數據並將其推回到其他ClientsInfo或刪除元素。

  • 當connectToClients()被調用但不會改變它們時,clientConnector將訪問otherClientsInfo中的每個元素。

我的第一個問題是,是否我的假設是,如果兩個ClientUI和ClientConnector訪問otherClientsInfo的同時,將程序的炸彈,因爲線程不安全的?

如果是這種情況,那麼我該如何去訪問其他ClientsInfo線程安全的,或許在某個對象訪問它時以某種方式鎖定它?

+0

什麼的線程庫您使用? – hirschhornsalz 2009-10-06 09:43:12

+0

我使用Qt工具包,它調用因爲我在Linux/BSD 所以據我所知並行線程。從其他的答案,我想這也許是好主意 周圍創建矢量一類,也許使用互斥來它 控制訪問。好/壞主意? – Conor 2009-10-06 10:11:35

+0

好主意,像Pete Kirkhams的建議可能會對你最好。 – 2009-10-06 17:38:30

回答

0

如果ClientUI和ClientConnector同時訪問otherClientsInfo,程序是否會因線程不安全而彈出?
是的,STL容器不是線程安全的。

如果是這種情況,那麼我該如何去訪問其他ClientsInfo線程安全的,或許在某個對象訪問它時鎖定它?
在最簡單的情況下,訪問共享數據周圍的互斥模式......如果您有多個讀者,那麼您會選擇更高效的模式。

+0

這是我的理解,互斥鎖阻止線程訪問相同功能中的數據,這是正確的嗎? 也許我誤解了你的答案,但是程序中發生的事情是vectorClientInfo可能同時被兩個不同類型的對象訪問,互斥鎖會阻止一個對象訪問它,而另一個對象訪問它嗎? 此外,您還可以點我在讀者和相關的模式很好的參考的方向是什麼? 謝謝你的回覆。 – Conor 2009-10-06 09:56:22

+0

互斥鎖是幫助您避免同時訪問關鍵數據的工具,例如參見http://en.wikipedia.org/wiki/Mutual_exclusion – 2009-10-06 10:07:47

+0

而且是的,問題是同時訪問......並且這就是鎖之類的互斥鎖幫你。 – 2009-10-06 10:12:16

0

clientConnector是否從與synchClientInfo()相同的線程中調用(即使它是全部回調)? 如果是這樣,你根本不用擔心線程安全。

如果要避免同時訪問相同的數據,可以使用互斥鎖來保護關鍵部分。對於exmample,mutexes from Boost::Thread

1

我的第一個問題是,是否我的假設是,如果兩個ClientUI和ClientConnector訪問otherClientsInfo的同時,將程序的炸彈,因爲線程不安全的?

是的。 std::vector的大多數實現不允許併發讀取和修改。 (你會知道,如果你使用one which did

如果是這樣的話,那麼我將如何去進行訪問otherClientsInfo線程安全的,在某種程度上也許當一個對象訪問它鎖了嗎?

無論何時只要訪問矢量,您都需要至少鎖定一個鎖(無論是簡單的互斥鎖還是臨界區或讀/寫鎖)。既然你只有一個讀寫器,那麼讀/寫鎖就沒有意義了。

然而,實際上這樣做正確將得到越來越困難,因爲你是暴露TE矢量其他類,因此必須揭露鎖定原語也,記住,只要你使用向量來獲取它。它可能是更好,以暴露addClientInforemoveClientInfo和const和非const foreachClientInfo功能,其封裝在Client類的鎖定,而不是由客戶端浮動左右的地方所擁有的數據的不相交的位。

+0

我正在使用QT工具包,它有一個QVector類,其功能 是可重入的。我不知道是否會重入解決我的問題在 這種情況下,反而會從QVector推導或類中封裝 的std ::載體,爲您提供建議 與功能互斥爲我提供了一個解決方案嗎? – Conor 2009-10-06 10:01:30

+0

將互斥量放在所有對向量的訪問中將提供一個解決方案。如果不暴露向量,那麼所有訪問都會發生在一個類中,因此操作它的函數會更容易。我不知道QT,所以不能真正評論它是否安全。 – 2009-10-06 10:07:07

+0

然後,只需將包裝類的指針傳遞給ClientConnector和ClientUI的構造函數 ?我可能會採取這個想法,並將其與QVector一起使用,如果使用QT編碼 ,那麼使用QT的類型可能更有意義...非常感謝您的幫助。 – Conor 2009-10-06 10:16:21

0

爲了確保從多個線程訪問otherClientsInfo成員是安全的,你需要用互斥鎖來保護它。我寫了一篇關於如何直接對象在C互斥量​​關聯的文章++以上的博士道博的網站:

http://www.drdobbs.com/cpp/225200269