STL是否为空()线程安全?

时间:2010-11-17 14:31:28

标签: stl thread-safety

我有多个线程修改stl向量和stl列表 如果容器是空的,我想避免必须锁定

以下代码是否是线程安全的?如果项目是列表或地图怎么办?

class A  
{  
    vector<int> items  
    void DoStuff()  
    {  
        if(!items.empty())  
        {  
            AquireLock();  
            DoStuffWithItems();  
            ReleaseLock();  
        }  
     }  
}  

5 个答案:

答案 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();  
        }
     }
 }