2012-06-11 61 views
3

我有一个多线程应用程序(使用std :: thread)和一个管理器(类树),它在不同的子树上执行某段代码(嵌入式结构子树)在平行下。基本思想是每个SubTree实例都有一个存储对象的双端队列。如果双端队列为空,则线程将等待,直到在双端队列中插入新元素或达到终止条件。一个子树可以生成对象并将它们推送到另一个子树的双端队列中。为了方便起见,我所有的std :: mutex,std :: locks和std :: variable_condition都存储在一个名为“locks”的结构中。C++在调用std :: unique_lock之前解锁std :: mutex等待

类树创建运行下面的方法(第一次尝试)某些线程:

void Tree::launch(SubTree & st, Locks & locks) 
{ 
/* some code */ 

std::lock_guard<std::mutex> deque_lock(locks.deque_mutex_[st.id_]) ; // lock the access to the deque of subtree st 
if (st.deque_.empty()) // check that the deque is still empty 
{ 
    // some threads are still running, wait for them to terminate 

    std::unique_lock<std::mutex> wait_lock(locks.restart_mutex_[st.id_]) ; 
    locks.restart_condition_[st.id_].wait(wait_lock) ; 
} 

/* some code */ 
} 

的问题是,当线程正在等待“deque_lock”仍处于锁定状态。因此,没有对象可以被并发的对象添加到当前线程的双端队列中。

所以我把lock_guard成unique_lock和管理的手动锁定/解锁:

void launch(SubTree & st, Locks & locks) 
{ 
/* some code */ 

std::unique_lock<std::mutex> deque_lock(locks.deque_mutex_[st.id_]) ; // lock the access to the deque of subtree st 
if (st.deque_.empty())   // check that the deque is still empty 
{ 
    deque_lock.unlock() ; // unlock the access to the deque to enable the other threads to add objects 

    // DATA RACE : nothing must happen to the unprotected deque here !!!!!! 

    // some threads are still running, wait for them to terminate 

    std::unique_lock<std::mutex> wait_lock(locks.restart_mutex_[st.id_]) ; 
    locks.restart_condition_[st.id_].wait(wait_lock) ; 
} 

/* some code */ 
} 

现在的问题,是有数据的比赛,我想,以确保“等待“指令直接在”deque_lock.unlock()“之后执行。有谁会知道用标准库创建这样一个关键指令序列的方法吗?

在此先感谢。

回答

0

这是一个很好的做法不承担,当您从等待条件变量返回,你等待条件满足

我宁愿写代码:

std::unique_lock<std::mutex> deque_lock(locks.deque_mutex_[st.id_]); 
while(st.deque_.empty()) 
{ 
    deque_lock.unlock(); 
    std::unique_lock<std::mutex> wait_lock(locks.restart_mutex_[st.id_]); 
    locks.restart_condition_[st.id_].wait(wait_lock); 
    deque_lock.lock(); 
} 

此代码保证,那一段时间后,你的队列不为空。 std::condition_variable::wait甚至可以用一个谓词来模拟这个行为之王(但是,由于队列锁定,它不能在这里使用)。

+0

感谢您的快速回答和建议,我会在我的代码中考虑到这一点。但是,在“deque_lock.unlock();”之后没有保证没有并发线程不会在双端队列中添加对象。然后当前线程将等待,而该deque不是空的。因此,我认为这里仍然存在数据竞赛。 –

+1

这取决于你想要在队列中拥有什么状态。条件变量经常用于等待,而队列不是空的,有两个元素不会打扰你。作为事后的想法,我想知道,为什么不用一个互斥体排除对队列和锁定条件变量的访问,即只使用'locks.deque_mutex_ [st.id]'。这将完全排除你的数据竞争(如果这是一个合理的解决方案,我不能说这些代码部分)。 –

相关问题