У меня есть класс очереди, данные которой хранятся в векторе:C++ очистка очереди и безопасность потока
std::vector<boost::shared_ptr<rxImage> > queue;
Существует поток, который добавляет к очереди, которая основана на этом цикле:
while(runRxThread){
this->rxImage();
}
Где rxImage() определяется по формуле:
zmq::message_t img;
imageSocket->recv(&img);
//addToQueue is a push back:
//queue.push_back(boost::shared_ptr<rxImage> (new rxImage(data, imgSize)));
localQueue->addToQueue((unsigned char*) img.data());
изображения, полученные в порядке в этой теме (я тестировал с 10000 или так, и это кажется прекрасным).
переменнаяrunRxThread устанавливается через некоторые функции инкубационные в классе, что функция потока определяется в
При выполнении процесса в основном потоке, таких как:.
startRx(); //start the thread
/*process to stimulate the sending of network data from another program*/
stopRX(); //stop the thread from accessing the queue
queue.clear();
Существует segfault, вызванный clear(). Я проверил, что это определенно эта линия, а не внутренняя сантехника объектов, и это определенно есть.
Как представляется, проблема безопасности потоков, но я не знаю, как ее исправить, и, что более важно, я не знаю почему. Я понимаю, что два потока могут записываться в одну и ту же память, но не в одно и то же время. Разумеется, установив переменные runRxThread, я гарантирую, что этого не произойдет.
Мне очень понравилось бы решение, которое не связано с мьютексами или семафорами - я действительно не думаю, что они должны быть необходимы для такой проблемы.
Спасибо!
EDIT: runRXThread летуч и петля нити теперь:
while(1){
if(runRxThread == 1){
this->rxImage();
}
}
EDIT2: «использовать семафор разделяемых объектов»
ОК, это явно проблема безопасности нити, мне нужно сделайте мои общие переменные потокобезопасными. Но ...
1) rxImage(); не прекращается, если не отправляются данные
2) Сегфакт происходит в пределах rxImage();
3) Если я заблокировать очереди с взаимной блокировкой, конечно, программа будет висеть в rxImage пока нет данных, потому что мьютекс не будет выпущен
4) Там не будет никаких данных, посланные, чтобы программа будет вечно вечно.
Возможно, это неправильно?
EDIT3:
Я изменил rxImage(), чтобы быть не блокировка:
zmq::message_t img;
imageSocket->recv(&img,ZMQ_NOBLOCK);
if((int)img.size() > 0){
cout<<"in the thread conditional"<<endl;
localQueue->addToQueue((unsigned char*) img.data());
cout<<"leaving thread conditional"<<endl;
}
Проблема раньше было очевидно, что localQueue писался, когда я убирала очередь. Теперь очередь может быть записана только в этой функции, когда есть данные для ее записи.Я могу гарантировать, что, когда я вызываю clear(), нет данных для записи, ((int) img.size()> 0) возвращает false, а очередь не обращается к потоку. Почему все еще существует segfault? Несомненно, это доказывает, что этот поток не вызывает segfault?
Вот терминальный вывод:
in the thread
pushing back1 of size: 16000000
Added image to queue. queue size: 650
leaving thread conditional
image server stopped
stopping image server
clearing vector
Segmentation fault
Можно видеть, что поток завершается с вектором, то сервер изображение останавливается, то вектор очищается. Именно в этом порядке без какого-либо непредсказуемого поведения. Но есть еще segfault.
Re. Изменить: volatile не является потокобезопасным в C++. Вам нужны синхронизация/доступ к атомной памяти – sehe
Да, вам нужно вызвать imageSocket-> recv (&img);), чтобы прервать его как-то. Обычно api связи имеет функцию Stop() или Abort(), которая является потокобезопасной и которую вы можете вызвать из stopRX() Это приведет к тому, что recv вызовет исключение или вернет код ошибки. Когда вы получите эту ошибку, вернитесь из rxImage(). –
Спасибо, я добавил неблокирующую версию функции, чтобы остановить зависание, см. Edit three. – user2290362