原子int集合的线程安全
Threadsafety of atomic int collection
我有以下 class 包装原子整数向量 ( std::vector< std::atomic_int >
)
矢量在构建对象时正确调整大小并且不会改变大小。有用于获取、设置原子整数的常用访问器和修改器,但没有守卫/互斥量。
class MyList
{
std::vector< std::atomic_int > collection_;
static MyList myList_;
public:
MyList() : collection_( MAX_SIZE, 0 ) {}
static MyList& getMyList() { return myList_; }
void set( size_t idx, int val )
{
collection_[idx].store( val, std::memory_order_relaxed );
}
int get( size_t idx ) const
{
return collection_[idx].load( std::memory_order_relaxed );
}
};
我怀疑这可能不是线程安全的(目前 运行 在单线程模型中没有问题),但希望能有任何意见。我想我主要关心的是无保护集合的线程安全,而不是它的元素。
首先,重要的是要注意您 can't have a vector of atomic ints 没有一些恶作剧。
忽略这一点,根据 [container.requirements.dataraces] 如果您只访问向量以修改其内容,那么这似乎是线程安全的。
For purposes of avoiding data races (17.6.5.9), implementations shall consider the following functions to be
const: begin, end, rbegin, rend, front, back, data, find, lower_bound, upper_bound, equal_range, at
and, except in associative or unordered associative containers, operator[].
Notwithstanding (17.6.5.9), implementations are required to avoid data races when the contents of the con-
tained object in different elements in the same container, excepting vector<bool>, are modified concurrently.
关于 operator[]
在这种情况下是否可能是非线程安全的措辞不是很清楚,但实际上没有合理的实现应该违反这一点。
如果您想要更多保证,并且由于矢量不会改变大小,您可以将 vector<T>
替换为 unique_ptr<T[]>
,这在这种情况下是线程安全的。
此外,您应该使用保证安全同步和排序的内存顺序(除非您有充分的理由),而不是 memory_order_relaxed
。根本不指定内存顺序,或使用 memory_order_acquire
/memory_order_release
对执行此操作。
这导致以下非常相似的代码:
class MyList
{
std::unique_ptr< std::atomic_int[] > collection_;
static MyList myList_;
public:
MyList() : collection_( new atomic_int[MAX_SIZE] ) {}
static MyList& getMyList() { return myList_; }
void set( size_t idx, int val )
{
collection_[idx].store( val, std::memory_order_release );
}
int get( size_t idx ) const
{
return collection_[idx].load( std::memory_order_acquire );
}
};
我有以下 class 包装原子整数向量 ( std::vector< std::atomic_int >
)
矢量在构建对象时正确调整大小并且不会改变大小。有用于获取、设置原子整数的常用访问器和修改器,但没有守卫/互斥量。
class MyList
{
std::vector< std::atomic_int > collection_;
static MyList myList_;
public:
MyList() : collection_( MAX_SIZE, 0 ) {}
static MyList& getMyList() { return myList_; }
void set( size_t idx, int val )
{
collection_[idx].store( val, std::memory_order_relaxed );
}
int get( size_t idx ) const
{
return collection_[idx].load( std::memory_order_relaxed );
}
};
我怀疑这可能不是线程安全的(目前 运行 在单线程模型中没有问题),但希望能有任何意见。我想我主要关心的是无保护集合的线程安全,而不是它的元素。
首先,重要的是要注意您 can't have a vector of atomic ints 没有一些恶作剧。
忽略这一点,根据 [container.requirements.dataraces] 如果您只访问向量以修改其内容,那么这似乎是线程安全的。
For purposes of avoiding data races (17.6.5.9), implementations shall consider the following functions to be const: begin, end, rbegin, rend, front, back, data, find, lower_bound, upper_bound, equal_range, at and, except in associative or unordered associative containers, operator[].
Notwithstanding (17.6.5.9), implementations are required to avoid data races when the contents of the con- tained object in different elements in the same container, excepting vector<bool>, are modified concurrently.
关于 operator[]
在这种情况下是否可能是非线程安全的措辞不是很清楚,但实际上没有合理的实现应该违反这一点。
如果您想要更多保证,并且由于矢量不会改变大小,您可以将 vector<T>
替换为 unique_ptr<T[]>
,这在这种情况下是线程安全的。
此外,您应该使用保证安全同步和排序的内存顺序(除非您有充分的理由),而不是 memory_order_relaxed
。根本不指定内存顺序,或使用 memory_order_acquire
/memory_order_release
对执行此操作。
这导致以下非常相似的代码:
class MyList
{
std::unique_ptr< std::atomic_int[] > collection_;
static MyList myList_;
public:
MyList() : collection_( new atomic_int[MAX_SIZE] ) {}
static MyList& getMyList() { return myList_; }
void set( size_t idx, int val )
{
collection_[idx].store( val, std::memory_order_release );
}
int get( size_t idx ) const
{
return collection_[idx].load( std::memory_order_acquire );
}
};