我有多个线程修改stl向量和stl列表 如果容器是空的,我想避免必须锁定
以下代码是否是线程安全的?如果项目是列表或地图怎么办?
class A
{
vector<int> items
void DoStuff()
{
if(!items.empty())
{
AquireLock();
DoStuffWithItems();
ReleaseLock();
}
}
}
答案 0 :(得分:6)
这取决于你的期望。其他答案是正确的一般,标准C ++容器不是线程安全的,此外,特别您的代码不会阻止修改容器的另一个线程在致电empty
和获取锁定之间(但此事与vector::empty
的线程安全无关。)
所以,为了避免任何误解:您的代码不保证items
在该区块内不会为空。
但是您的代码仍然有用,因为您要做的就是避免冗余锁定创建。您的代码不提供保证,但可能可防止不必要的锁定创建。它在所有情况下都不起作用(其他线程仍然可以在检查和锁之间清空容器)但在一些情况下。如果您只是通过省略冗余锁来进行优化,那么您的代码就可以实现这一目标。
只需确保对容器的任何实际访问 受锁保护。
顺便说一句,上面的严格来说未定义的行为:理论上允许STL实现在{{1}的调用中修改mutable
成员}}。这意味着对empty
的明显无害(因为只读)调用实际上会导致冲突。不幸的是,你不能依赖于只读调用对STL容器是安全的假设。
但在实践中,我非常确定empty
将不修改任何成员。但是对于vector::empty
我已经不太确定了。如果你真的想要保证,那么要么锁定每个访问权限,要么不要使用STL容器。
答案 1 :(得分:3)
对STL的容器和算法中的任何内容都没有线程安全保证。
所以,不。
答案 2 :(得分:2)
无论空是否是线程安全的,您的代码都不会像写的那样实现您的目标。
class A
{
vector<int> items
void DoStuff()
{
if(!items.empty())
{
//Another thread deletes items here.
AquireLock();
DoStuffWithItems();
ReleaseLock();
}
}
}
更好的解决方案是每次使用items
时进行锁定(迭代,获取项目,添加项目,检查计数/空白等),从而提供自己的线程安全性。因此,首先获取锁定,然后检查向量是否为空。
答案 3 :(得分:1)
STL不是线程安全的,也是空的。如果您希望make container安全,则必须通过互斥或其他同步关闭所有方法
答案 4 :(得分:1)
正如已经回答的那样,上面的代码不是线程安全的,并且在实际对容器执行任何操作之前必须进行锁定。 但是以下应该比总是锁定更好的性能,我不能想到它可能不安全的原因。 这里的想法是锁定可能是昂贵的,我们正在避免它,只要不是真的需要它。
class A
{
vector<int> items;
void DoStuff()
{
if(!items.empty())
{
AquireLock();
if(!items.empty())
{
DoStuffWithItems();
}
ReleaseLock();
}
}
}