2012-02-16 46 views
1

下面的代碼會給我一個錯誤,因爲boost :: mutex是不可複製的,而xyz.push_back()是一個拷貝構造函數。Boost,指向一個互斥體,將工作? boost :: mutex和std :: vector,不可複製的問題

class XYZ 
{ 
    public: 
     double x; 
     boost::mutex x_mutex; 
} 

vector<XYZ> xyz; 
xyz.push_back(XYZ()); 

所以,我想這樣的事情,

class XYZ 
{ 
    public: 
     double x; 
     boost::mutex * x_mutex; 
} 

vector<XYZ> xyz; 
xyz.push_back(XYZ()); 

它符合任何錯誤,但問題是「將是互斥的實際工作,因爲它應該是什麼?」這是在類中封裝互斥鎖的好方法,然後創建該類的向量?

謝謝。

+2

無論它是否工作,都取決於您是否正確使用互斥鎖。但有一點是肯定的:如果你不明白你的互斥體和/或互斥體指針發生了什麼,你可能會遇到一些麻煩。 – 2012-02-16 23:19:44

回答

6

這裏有兩個問題:

  1. 將互斥正確創建?

  2. 互斥體的使用是否正確?

由於問題的答案是1.是否。互斥體指針不指向互斥體。

所以你需要添加一個合適的構造函數。 因爲你需要一個構造函數,所以如果你希望你的類正確行爲,你可能需要實現析構函數,複製構造函數和賦值運算符。

要麼

XYZ::XYZ() : x(0), x_mutex(new boost::mutex) {} 
XYZ::~XYZ() { delete x_mutex; } 
XYZ::XYZ(const XYZ & xyz) : x(xyz.x), x_mutex(new boost::mutex) {} 
XYZ& XYZ::operator=(const XYZ & xyz) { x=xyz.x; } 

explicit XYZ::XYZ(boost::mutex * m) : x(0), x_mutex(m) {} 
// Strictly speaking we dont need these as the default version does the right thing. 
XYZ::~XYZ() {} 
XYZ::XYZ(const XYZ & xyz) : x(xyz.x), x_mutex(xyz.x_mutex) {} 
XYZ& XYZ::operator=(const XYZ & xyz) { x=xyz.x; x_mutex = xyz.x_mutex; } 

將是我的期望。

在第一種情況下,對象的每個實例和副本都有其自己的互斥鎖。在第二個對象與它的副本共享一個互斥量,但互斥量必須在實例之前創建。

還有第三種變體,其中互斥體可以由構造函數創建並與所有實例共享,但要做到這一點,您需要對互斥鎖而不是原始指針執行shared_ptr

class XYZ 
{ 
    public: 
    double x; 
    boost::shared_ptr<boost::mutex> x_mutex; 
    XYZ() : x(0), x_mutex(new boost::mutex) {} 
    // Default versions of the other three do the right thing. 
}; 

如果我們找不到這些路徑中的任何一個,最終會出現互斥體被正確創建和初始化的情況。

現在的棘手部分「互斥體是否能正確使用?」。爲了回答這個問題,我們需要知道線程之間如何共享對象,互斥體應該保護的共享數據是什麼。

如果在創建任何工作線程之前在主線程中創建了對象的向量,並且每個對象實例都已被工作線程修改(這樣互斥量確實在保護x數據),那麼第一個版本如果可能正確。在這種情況下,你的代碼看起來更像這樣。

//Main thread 
std::vector<XYZ> v; 
for(unsigned int i=0; i<10; ++i) 
    v.push_back(XYZ()); 

//Several worker threads like this 
j = rand()%10; 
v[j].x_mutex->lock(); 
v[j].x+=1; 
v[j].x_mutex->unlock(); 

如果x確實是一個指針類型,它指向的線程之間共享你的代碼可能看起來像這樣的事情,正確版本的代碼使用的是2或3

//Main thread 
std::vector<XYZ> v; 
X * xa; 
boost::mutex xa_mutex; 
X * xb; 
boost::mutex xb_mutex; 

for(unsigned int i=0; i<5; ++i) 
    v.push_back(XYZ(xa,xa_mutex)); 

for(unsigned int i=0; i<5; ++i) 
    v.push_back(XYZ(xb,xb_mutex)); 

//Several worker threads like this 
j = rand()%10; 
v[j].x_mutex->lock(); 
v[j].x->do_something(); 
v[j].x_mutex->unlock(); 

關鍵是每個共享資源有一個互斥鎖。

請注意,從技術上講,矢量v在這兩種情況下都是共享資源,如果要在創建後更改,它也應該受互斥鎖保護。然而,這樣的鎖可以(正確地)銷燬所有的並行性,所以我們暫時忽略它;)

+0

謝謝Michael,我設法使用共享指針來工作。 – 2607 2012-02-21 03:31:24

相關問題