Effective STL 第12条

2022-09-10  本文已影响0人  懒生活

容器的线程安全性

不能对容器的线程安全性抱太大的期望

对于stl容器,大部分容器只能保证
1)支持多线程同时读
2)支持多线程对不同的容器同时进行写
容器读写的线程安全性要靠用户自己保证.

  vector<int> v;
  vector<int>::iterator first5(find(v.begin(), v.end(),5));
  if(first5!=v.end())
    *first5 = 12;

对于上面这段代码,如果在找到并构建first5之后,如果有其它的线程对v进行了操作,如删除中间某个元素,直接会导致这个迭代器失效.此时线程的安全性就出现问题了.
为了保证线程安全,上面的代码要做如下的互斥

#include <mutex>
vector<int> v{ 1,3,4,5,56 };
std::mutex mutexForV;
int main()
{
    mutexForV.lock();
    vector<int>::iterator first5(std::find(v.begin(), v.end(), 5));
    if(first5!=v.end())
        *first5 = 15;
    mutexForV.unlock();
}

更好的手动互斥手段

上面的互斥手段依赖于lock和unlock, 如果在lock之后,发生异常, 那么永远不会执行unlock. 这可能会导致死锁. 使用lock_gard优化上面的代码. 因为c++保证,在发生异常的时候,创建的局部变量都会被析构.这样mutexForV_gard不管什么时候发生异常,离开作用域后肯定会被析构掉,析构的时候,可能会释放锁. 不光是保证了异常安全,而且也避免了编码时忘记unlock的风险.

vector<int> v{ 1,3,4,5,56 };
std::mutex mutexForV;
int main()
{
    std::lock_guard<std::mutex> mutexForV_gard(mutexForV);
    vector<int>::iterator first5(std::find(v.begin(), v.end(), 5));
    if(first5!=v.end())
        *first5 = 15;
}
上一篇下一篇

猜你喜欢

热点阅读