簡體   English   中英

Boost,指向互斥量的指針,會起作用嗎? boost :: mutex和std :: vector,不可復制的問題

[英]Boost, pointer to a mutex, will that work? boost::mutex and std::vector, noncopyable issue

以下代碼會給我一個錯誤,因為boost :: mutex是不可復制的,而xyz.push_back()是復制構造函數。

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());

它沒有錯誤,但是問題是“互斥鎖實際上會按預期工作嗎?” 這是將互斥體封裝在類中,然后創建該類的向量的好方法嗎?

謝謝。

這里有兩個問題:

  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在兩種情況下都是共享資源,並且如果要在創建后對其進行更改,則也應使用互斥量進行保護。 但是,這樣的鎖會(正確地)破壞所有並行性..因此,讓我們暫時忽略它;)

暫無
暫無

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

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