【发布时间】:2017-05-12 21:03:00
【问题描述】:
我尝试了不同的方法,但是双端队列容器中线程的 push_back 反应很奇怪。
为什么会这样??这是因为复制/移动构造函数吗?
这里是程序的输出...
progress[0]:-1
progress[1]:-1
executing threads...
progress[0]:100
progress[1]:100
================================
progress[0]:-1
progress[1]:-1
executing threads...
progress[0]:-1
progress[1]:100
如输出所示,结果在使用之间有所不同
for(size_t i = 0; i < 2; ++i) {
deq.push_back(th(&progress[i]));
}
和
deq.push_back(th(&progress[0]));
deq.push_back(th(&progress[1]));
这是源代码...
class th {
public:
void func() {
*this->progress = 100;
}
th(int* prog) :
progress(prog),
m_thread(std::thread(&th::func, this)) {};
// COPY
th(th const& other);
th& operator=(th const& other);
// MOVE
th(th&&) = default;
// th& operator=(th&& other) {
// if(this != &other){
// }
// return *this;
// }
void join() { m_thread.join(); }
int *progress;
private:
std::thread m_thread;
};
int main(void) {
{
std::vector<int> progress;
progress.push_back(-1);
progress.push_back(-1);
std::deque<th> deq;
std::cout << "progress[0]:" << progress[0] << std::endl;
std::cout << "progress[1]:" << progress[1] << std::endl;
std::cout << "executing threads..." << std::endl;
deq.push_back(th(&progress[0]));
deq.push_back(th(&progress[1]));
for (std::deque<th>::iterator it = deq.begin(); it != deq.end(); it++) {
it->join();
// deq.erase(it);
}
std::cout << "progress[0]:" << progress[0] << std::endl;
std::cout << "progress[1]:" << progress[1] << std::endl;
}
std::cout << "================================" << std::endl;
{
std::vector<int> progress;
progress.push_back(-1);
progress.push_back(-1);
std::deque<th> deq;
std::cout << "progress[0]:" << progress[0] << std::endl;
std::cout << "progress[1]:" << progress[1] << std::endl;
std::cout << "executing threads..." << std::endl;
for(size_t i = 0; i < 2; ++i) {
deq.push_back(th(&progress[i]));
}
for (std::deque<th>::iterator it = deq.begin(); it != deq.end(); it++) {
it->join();
// deq.erase(it);
}
std::cout << "progress[0]:" << progress[0] << std::endl;
std::cout << "progress[1]:" << progress[1] << std::endl;
}
exit(EXIT_SUCCESS);
}
以及如何在没有编译器抱怨的情况下使用 deque 的擦除成员函数
/home/user/test/obj/main.o: In function `__gnu_cxx::_Mutable_BidirectionalIteratorConcept<th*>::__constraints()':
main.cpp:(.text._ZN9__gnu_cxx37_Mutable_BidirectionalIteratorConceptIP2thE13__constraintsEv[__gnu_cxx::_Mutable_BidirectionalIteratorConcept<th*>::__constraints()]+0x40): undefined reference to `th::operator=(th const&)'
/home/user/test/obj/main.o: In function `__gnu_cxx::_ConvertibleConcept<th, th>::__constraints()':
main.cpp:(.text._ZN9__gnu_cxx19_ConvertibleConceptI2thS1_E13__constraintsEv[__gnu_cxx::_ConvertibleConcept<th, th>::__constraints()]+0x20): undefined reference to `th::th(th const&)'
/home/user/test/obj/main.o: In function `__gnu_cxx::_OutputIteratorConcept<th*, th>::__constraints()':
main.cpp:(.text._ZN9__gnu_cxx22_OutputIteratorConceptIP2thS1_E13__constraintsEv[__gnu_cxx::_OutputIteratorConcept<th*, th>::__constraints()]+0x64): undefined reference to `th::operator=(th const&)'
/home/user/test/obj/main.o: In function `th* std::__copy_move_backward<true, false, std::random_access_iterator_tag>::__copy_move_b<th*, th*>(th*, th*, th*)':
main.cpp:(.text._ZNSt20__copy_move_backwardILb1ELb0ESt26random_access_iterator_tagE13__copy_move_bIP2thS4_EET0_T_S6_S5_[th* std::__copy_move_backward<true, false, std::random_access_iterator_tag>::__copy_move_b<th*, th*>(th*, th*, th*)]+0x5c): undefined reference to `th::operator=(th const&)'
/home/user/test/obj/main.o: In function `th* std::__copy_move<true, false, std::random_access_iterator_tag>::__copy_m<th*, th*>(th*, th*, th*)':
main.cpp:(.text._ZNSt11__copy_moveILb1ELb0ESt26random_access_iterator_tagE8__copy_mIP2thS4_EET0_T_S6_S5_[th* std::__copy_move<true, false, std::random_access_iterator_tag>::__copy_m<th*, th*>(th*, th*, th*)]+0x44): undefined reference to `th::operator=(th const&)'
/home/user/test/obj/main.o: In function `__gnu_cxx::_Mutable_ForwardIteratorConcept<th*>::__constraints()':
main.cpp:(.text._ZN9__gnu_cxx31_Mutable_ForwardIteratorConceptIP2thE13__constraintsEv[__gnu_cxx::_Mutable_ForwardIteratorConcept<th*>::__constraints()]+0x3c): undefined reference to `th::operator=(th const&)'
collect2: ld returned 1 exit status
make: *** [link] Error 1
谢谢!
【问题讨论】:
-
// deq.erase(it);是怎么回事?哦,是的,你的th是错误的。它不应该是可复制的,并且应该正确实现移动语义 (noexcept)。 -
如上所述编译器在使用它时会抱怨!
-
@mmmint 你有竞争条件,
std::deque不是线程安全容器。 -
您将指针
this传递给std::thread的构造函数。将th对象移动到deque后,this的值不再有效,因为该对象现在已移动到不同的位置。然而线程仍然使用旧值。尝试使th不可移动并使用emplace_back而不是push_back。 -
出于同样的原因,如果从容器中删除其他
th对象(以填充孔),则必须移动th对象,因此您将无法erase来自deque的对象与您的设计。
标签: c++ multithreading deque