我为SFML编写了一个线程渲染器,它接受指向可绘制对象的指针,并将它们存储在一个向量中以绘制每一帧。开始向向量添加对象并将对象移除到向量将经常导致分段错误(SIGSEGV)。为了尝试解决这个问题,我会添加需要删除/添加到队列中的对象以便稍后删除(在绘制帧之前)。这似乎解决了这个问题,但最近我注意到,如果我一次添加许多对象(或者足够快地添加/删除它们),我将获得相同的SIGSEGV。
当我从向量中添加/删除时,我应该使用锁吗?
答案 0 :(得分:3)
您需要了解线程安全保证C ++标准(以及可能并发系统的C ++ 2003实现)。标准容器在以下意义上是线程安全的:
许多人误解容器的线程安全意味着这些规则是由容器实现强加的:它们不是!遵守这些规则是你的责任。
这些不是,实际上不能由容器施加的原因是它们没有适合这种情况的界面。例如,考虑以下一些简单的代码:
if (!c.empty() {
auto value = c.back();
// do something with the read value
}
容器可以控制对empty()
和back()
的调用的访问权限。但是,在这些调用之间,它必然需要释放任何类型的同步工具,即在线程尝试读取c.back()
时,容器可能再次为空!基本上有两种方法可以解决这个问题:
回答原始问题:是的,您需要使用外部同步,例如:以互斥锁的形式,如果你在一个线程中修改容器并在另一个线程中读取它。
答案 1 :(得分:1)
当我从向量中添加/删除时,我应该使用锁吗?
是。如果您同时使用来自两个线程的向量并重新分配,则可以交换支持分配并释放在另一个线程的脚后面。另一个线程将读取/写入释放的内存,或者用于另一个不相关分配的内存。