Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+中是否存在任何并发容器+;11?_C++_Visual Studio 2010_Concurrency_C++11_Blockingqueue - Fatal编程技术网

C++ C+中是否存在任何并发容器+;11?

C++ C+中是否存在任何并发容器+;11?,c++,visual-studio-2010,concurrency,c++11,blockingqueue,C++,Visual Studio 2010,Concurrency,C++11,Blockingqueue,特别是,我正在寻找一个阻塞队列。C++11中有这样的东西吗?如果没有,我的其他选择是什么?我真的不想再深入到线程级别了。太容易出错了。: 一个反复出现的问题(嗯,是众多问题中的一个)是关于STL容器的 以及它们是否是线程安全的 根据Stephan的话,现实是他们不是,不是作为一个整体 bug但作为一个特性:拥有每个STL的每个成员函数 获取内部锁的容器将破坏性能。作为 作为一个通用的、高度可重用的库,它实际上不会 提供正确性:放置锁的正确级别为 由程序正在执行的操作决定。从这个意义上说,个人 成

特别是,我正在寻找一个阻塞队列。C++11中有这样的东西吗?如果没有,我的其他选择是什么?我真的不想再深入到线程级别了。太容易出错了。

一个反复出现的问题(嗯,是众多问题中的一个)是关于STL容器的 以及它们是否是线程安全的

根据Stephan的话,现实是他们不是,不是作为一个整体 bug但作为一个特性:拥有每个STL的每个成员函数 获取内部锁的容器将破坏性能。作为 作为一个通用的、高度可重用的库,它实际上不会 提供正确性:放置锁的正确级别为 由程序正在执行的操作决定。从这个意义上说,个人 成员函数的级别往往不那么正确

(PPL)包括多个容器,这些容器提供对其元件的线程安全访问:

  • 是一个序列容器类,允许随机访问任何元素。它支持并发安全的追加、元素访问、迭代器访问和迭代器遍历操作
  • 是一个序列容器类,允许对其元素进行先进先出的访问。它支持有限的并发安全操作集,例如push和try_pop等
一些样品


同样有趣的是:。

容器的接口根本没有按照这个目标设计。对于它们使用的接口,客户端可见的锁实际上是在保证正确性和可预测行为的同时实现这一点的唯一方法。这也将是非常低效的,因为收购的数量将非常高(相对于良好的实施)

解决方案1

通过值(如适用)

解决方案2

创建一个简单的栓接实现集合,您可以使用这些实现在持有范围锁的同时传递容器(将其视为伪c++):

模板
类t_锁定_集合{
公众:
t_lock_collection(t收集和未收集,t_锁和锁):收集(未收集),d_锁(锁),d_nocopy(){
}
t收集和收集;
//你的便当
私人:
t_scope_lock d_lock;
t_nocopy d_nocopy;
};
然后调用方将锁与集合配对,然后在适当的地方更新接口以使用(传递)容器类型。这只是一个穷人的班级扩展

这个锁定的容器是一个简单的例子,还有一些其他的变体。这是我选择的路线,因为它确实允许您使用适合您的程序的粒度级别,即使它不如锁定方法那样透明(语法上)。适应现有的程序也相对容易。至少它的行为是可预测的,不像带有内部锁的集合

另一种变体是:

template <typename TCollection>
class t_lockable_collection {
public:
// ...
private:
    TCollection d_collection;
    t_mutex d_mutex;
};

// example:
typedef t_lockable_collection<std::vector<int> > t_lockable_int_vector;
模板
类t_可锁定_集合{
公众:
// ...
私人:
t收集d_收集;
t_mutex d_mutex;
};
//例如:
typedef t_lockable_collection t_lockable_int_vector;

…其中类似于
t\u locked\u collection
的类型可用于公开基础集合。并不是说这种方法是万无一失的,只是万无一失。

C++11本身并不提供并发容器。但是,还有一些库选项。 除了已经提到的PPL,不要忘记Intel TBB库

它有一个并发的
队列
哈希映射
集合
向量
实现。但它不仅是一个线程安全的容器库,它还附带了标准算法的并行版本(用于循环、减少、排序等)


我很惊讶没有人提到。我们已经使用它很长一段时间了,它的性能非常好。具体来说,它的实现是无锁的,这立即带来了巨大的速度。其他使用原因(引用官方网站):

<> C++没有完全成熟的无锁队列。促进 有一个,但它仅限于具有普通赋值运算符的对象 例如,一些简单的析构函数。英特尔的TBB队列不是 无锁,也需要简单的构造函数。有很多 在C++中实现无锁队列的学术论文,但可用 源代码很难找到,测试更是如此

提供了一些基准和比较,以及


警告:在多个生产者的情况下,弹出元素的顺序不保证与推送元素的顺序相同(@IgorLevicki),因此如果需要此保证,请寻找其他选项。

我的并发无序映射版本 命名空间并发 {

模板
类无序_bucket:private std::无序_map
{
可变std::递归互斥m互斥;
公众:
T1和运算符[](TA)
{
std::锁保护l(mumutex);
返回std::无序映射::运算符[](a);
}
size\u t size()常量noexcept{
std::锁保护l(mumutex);
返回std::无序映射::size();
}
向量toVector()常量
{
std::锁保护l(mumutex);
向量ret;
对于(常数对和p:*此)
{
后推回(p);
}
返回ret;
}
布尔查找(常量T&T)常量
{
std::锁保护l(mumutex);
如果(this->std::unordered_map::find(t)=this->end())
返回false;//未找到
返回true;
}
无效擦除()
{
std::锁保护l(mumutex);
此->无序映射::擦除(此->开始(),此->结束());
}
无效擦除(常数T&T)
{
std::锁保护l(mumutex);
这->无序映射::擦除(t);
}
};
#定义BUCKETCOUNT 10
模板
类并发映射
{
std::向量m_v;
公众:
ConcurrentMap():m_v(BUCKETCOUNT){}//使用10个存储桶
T1和运算符[](TA)
{
std::hash;
返回m_v[h(a)%BUCKETCOUNT][a];
}
size\u t size()常量noexcept{
尺寸=0;
用于(常量无序桶和ub:m_v)
碳纳米管=
template <typename TCollection>
class t_lockable_collection {
public:
// ...
private:
    TCollection d_collection;
    t_mutex d_mutex;
};

// example:
typedef t_lockable_collection<std::vector<int> > t_lockable_int_vector;
template<typename T,typename T1>
class unordered_bucket: private std::unordered_map<T,T1>
{
mutable std::recursive_mutex m_mutex;

public:
T1 &operator [](T a)
{
    std::lock_guard<std::recursive_mutex> l(m_mutex);
    return std::unordered_map<T,T1>::operator [](a);
}

size_t size() const noexcept {
    std::lock_guard<std::recursive_mutex> l(m_mutex);
    return  std::unordered_map<T,T1>::size();
}

vector<pair<T,T1>> toVector() const
{
    std::lock_guard<std::recursive_mutex> l(m_mutex);

    vector<pair<T,T1>> ret;
    for(const pair<T,T1> &p:*this)
    {
        ret.push_back(p);
    }
    return ret;
}

bool find(const T &t) const
{
    std::lock_guard<std::recursive_mutex> l(m_mutex);
    if(this->std::unordered_map<T,T1>::find(t) == this->end())
        return false;  //not found
    return true;
}
void erase()
{
    std::lock_guard<std::recursive_mutex> l(m_mutex);
    this->unordered_map<T,T1>::erase(this->begin(),this->end());
}
void erase(const T &t)
{
    std::lock_guard<std::recursive_mutex> l(m_mutex);
    this->unordered_map<T,T1>::erase(t);
}
};

#define BUCKETCOUNT 10
template<typename T,typename T1>
class ConcurrentMap
{
std::vector<unordered_bucket<T,T1>> m_v;
public:
ConcurrentMap():m_v(BUCKETCOUNT){}   //using 10 buckets

T1 &operator [](T a)
{
    std::hash<T> h;
    return m_v[h(a)%BUCKETCOUNT][a];
}

size_t size() const noexcept {
    size_t cnt=0;

    for(const unordered_bucket<T,T1> &ub:m_v)
        cnt=cnt+ub.size();

    return  cnt;
}

vector<pair<T,T1>> toVector() const
{
    vector<pair<T,T1>> ret;
    for(const unordered_bucket<T,T1> &u:m_v)
    {
        const vector<pair<T,T1>> &data=u.toVector();
        ret.insert(ret.end(),data.begin(),data.end());
    }
    return ret;
}

bool find(const T &t) const
{
    for(const unordered_bucket<T,T1> &u:m_v)
        if(true == u.find(t))
            return true;
    return false;
}
void erase()
{
    for(unordered_bucket<T,T1> &u:m_v)
        u.erase();
}
void erase(const T &t)
{
    std::hash<T> h;
    unordered_bucket<T,T1> &ub = m_v[h(t)%BUCKETCOUNT];
    ub.erase(t);
}
};
}