在我的多线程应用程序中,我有两个使用相同std::deque
的线程。其中一个写入它,而另一个读取它(用于数据分析)。
我收到此错误:
Deque iterator not dereferencable
修改
这是我用来从双端队列中读取的代码。错误在if条件更深处被抛出(我在at
访问双端队列的地方。)
for (int i = 0; i <myDeque.size(); i++){
try{
if (myDeque.at(i) > 10){
//do stufff
}
}
catch (...){
cout << "ERROR" << endl;
}
}
我认为,这是由于deque的多线程访问而发生的。
我无法通过try-catch
块捕获错误。我不能这样做,因为它被扔进了更深的飞机&#34;?
有可能修复此错误吗?
答案 0 :(得分:3)
以下是通过队列进行通信的读写器对的一个非常简单的示例。
请注意使用condition_variable来同步有关是否有工作要做以及编写器是否已完成的通信(表示读取器在清空队列时可以停止):
#include <iostream>
#include <thread>
#include <deque>
#include <condition_variable>
std::mutex m;
std::condition_variable reader_action;
bool all_written = false;
std::deque<int> buffer;
// note: this function is called with the mutex unlocked
// we have popped i from the buffer
void handle_read_event(int i)
{
if (i % 100000 == 0)
std::cout << i << std::endl;
}
int main()
{
std::thread writer([]{
for (int i = 0 ; i < 1000000 ; ++i)
{
{
auto lock = std::unique_lock<std::mutex>(m);
buffer.push_back(i);
lock.unlock();
reader_action.notify_one();
}
}
auto lock = std::unique_lock<std::mutex>(m);
all_written = true;
lock.unlock();
reader_action.notify_one();
});
std::thread reader([]{
while(1)
{
auto lock = std::unique_lock<std::mutex>(m);
reader_action.wait(lock, [] { return all_written || (!buffer.empty()); });
if (!buffer.empty()) {
int i = buffer.front();
buffer.pop_front();
lock.unlock();
handle_read_event(i);
}
else if(all_written)
{
break;
}
}
});
writer.join();
reader.join();
return 0;
}
预期产出:
0
100000
200000
300000
400000
500000
600000
700000
800000
900000
如果我们决定在排除队列时不介意让编写器等待,我们可以实现第二个线程:
std::thread reader([]{
while(1)
{
auto lock = std::unique_lock<std::mutex>(m);
reader_action.wait(lock, [] { return all_written || (!buffer.empty()); });
while (!buffer.empty()) {
int i = buffer.front();
buffer.pop_front();
handle_read_event(i);
}
if(all_written)
{
break;
}
}
});
......或任何其他适合我们目的的策略。
答案 1 :(得分:2)
使用锁定?在一些常用的位置,声明mutex
:
... nondeque stuff ...
{
std::lock_guard<std::mutex> lock(deque_lock);
mydeque.push_back(...);
}
... more nondeque stuff...
然后将读取和写入包裹在blocks that acquire it中的... nondeque stuff ...
{
std::lock_guard<std::mutex> lock(deque_lock);
for (const auto& elem : mydeque) {
... do stuff with each element, ideally cheap things to avoid blocking writer ...
}
}
... more nondeque stuff...
:
IEnumerator Fade(MeshRenderer myMesh)
{
for (float t = 0f; t < FadeTime; t += Time.deltaTime)
{
float normalizedTime = t / FadeTime;
_alpha = Mathf.Lerp(_startAlpha, _endAlpha, normalizedTime);
// The fix
myMesh.material.color = new Color (myMesh.material.color.r, myMesh.material.color.g, myMesh.material.color.b, _alpha);
yield return null;
}
//_alpha = _endAlpha;
//myMesh.material.color = new Color (myMesh.material.color.r, myMesh.material.color.g, myMesh.material.color.b, _alpha);
}
阅读时:
{{1}}
尝试在锁定的块中将工作保持在最低限度;如果它是昂贵的工作,可能值得复制掉锁下的值,然后在没有锁的情况下使用它来避免阻塞其他线程。