首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程安全无锁数组

线程安全无锁数组
EN

Stack Overflow用户
提问于 2013-06-04 13:59:54
回答 3查看 8.4K关注 0票数 8

我有一个C++库,它应该对多个线程进行一些计算。我编写了独立的线程代码(即它们之间没有共享变量),除了一个数组。问题是,我不知道如何保证线程安全。

我看了互斥锁/解锁(QMutex,因为我使用的是Qt),但它不适合我的任务-当一个线程将锁定互斥,其他线程将等待!

然后我读到了关于std::atomic的文章,它看上去就像我所需要的。然而,我试图以以下方式使用它:

代码语言:javascript
复制
std::vector<std::atomic<uint64_t>> *myVector;

它会产生编译器错误(使用已删除的函数‘std::atomic(const::atomic&)’)。然后我找到了the solution --为std::atomic使用特殊的包装器。我试过这个:

代码语言:javascript
复制
struct AtomicUInt64
{
    std::atomic<uint64_t> atomic;

    AtomicUInt64() : atomic() {}

    AtomicUInt64 ( std::atomic<uint64_t> a ) : atomic ( atomic.load() ) {}

    AtomicUInt64 ( AtomicUInt64 &auint64 ) : atomic ( auint64.atomic.load() ) {}

    AtomicUInt64 &operator= ( AtomicUInt64 &auint64 )
    {
                atomic.store ( auint64.atomic.load() );
    }
};

std::vector<AtomicUInt64> *myVector;

这个东西编译成功,但是当我无法填充向量时:

代码语言:javascript
复制
myVector = new std::vector<AtomicUInt64>();

for ( int x = 0; x < 100; ++x )
{
    /* This approach produces compiler error:
     * use of deleted function 'std::atomic<long long unsigned int>::atomic(const std::atomic<long long unsigned int>&)'
     */
    AtomicUInt64 value( std::atomic<uint64_t>( 0 ) ) ;
    myVector->push_back ( value );

    /* And this one produces the same error: */
    std::atomic<uint64_t> value1 ( 0 );
    myVector->push_back ( value1 );
}

我做错了什么?我想我什么都试过了(也许没有,无论如何),没有什么能帮上忙。在C++中还有其他的线程安全数组共享方法吗?

顺便说一下,我在Windows上使用了MinGW 32位4.7编译器。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-06-04 14:31:53

下面是您的AtomicUInt64类型的清理版本:

代码语言:javascript
复制
template<typename T>
struct MobileAtomic
{
  std::atomic<T> atomic;

  MobileAtomic() : atomic(T()) {}

  explicit MobileAtomic ( T const& v ) : atomic ( v ) {}
  explicit MobileAtomic ( std::atomic<T> const& a ) : atomic ( a.load() ) {}

  MobileAtomic ( MobileAtomic const&other ) : atomic( other.atomic.load() ) {}

  MobileAtomic& operator=( MobileAtomic const &other )
  {
    atomic.store( other.atomic.load() );
    return *this;
  }
};

typedef MobileAtomic<uint64_t> AtomicUInt64;

和使用:

代码语言:javascript
复制
AtomicUInt64 value;
myVector->push_back ( value );

或者:

代码语言:javascript
复制
AtomicUInt64 value(x);
myVector->push_back ( value );

您的问题是,您按值获取了一个std::atomic,这会导致一个副本被阻塞。哦,你也没能从operator=回来。我还明确了一些构造函数,可能是不必要的。我将const添加到您的复制构造函数中。

我还会尝试将storeload方法添加到转发给atomic.storeatomic.loadMobileAtomic中。

票数 6
EN

Stack Overflow用户

发布于 2013-06-04 14:16:23

您正在尝试复制不可复制的类型:AtomicUInt64构造函数按值获取atomic

如果需要从atomic初始化它,那么它应该采用(const)引用的参数。然而,在您的情况下,看起来根本不需要从atomic初始化;为什么不从uint64_t初始化呢?

还有几个小问题:

  • 复制构造函数和赋值操作符应该通过const引用获取它们的值,以允许复制临时代码。
  • 使用new分配向量是一件很奇怪的事情;您只是在添加额外的间接方向,而没有任何好处。
  • 确保在其他线程可能访问数组时,不要调整数组的大小。
票数 2
EN

Stack Overflow用户

发布于 2013-06-04 14:18:14

这条线

代码语言:javascript
复制
AtomicUInt64 ( std::atomic<uint64_t> a ) : atomic ( atomic.load() ) {}

您完全忽略了传入的参数,您可能希望它是a.load(),并且您可能希望通过const引用获取元素,这样它们就不会被复制。

代码语言:javascript
复制
AtomicUInt64 (const std::atomic<uint64_t>& a) : atomic (a.load()) {}

至于你在做什么,我不确定它是否正确。数组中变量的修改将是原子的,但是如果向量被修改或重新分配(这在push_back中是可能的),那么就没有什么可以保证您的数组修改在线程之间工作,并且是原子的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16919858

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档