我有一个带有管理器(树类)的多线程应用程序(使用 std::thread),它在不同的子树(嵌入式结构子树)上并行执行一些代码。基本思想是 SubTree 的每个实例都有一个存储对象的双端队列。如果双端队列为空,则线程等待直到在双端队列中插入新元素或达到终止条件。一个子树可以生成对象并将它们推送到另一个子树的双端队列中。为方便起见,我所有的 std::mutex、std::locks 和 std::variable_condition 都存储在一个名为“locks”的结构中。
Tree 类创建了一些运行以下方法的线程(第一次尝试):
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()”指令之后直接执行“等待”指令。有人知道用标准库创建如此关键的指令序列的方法吗?
提前致谢。