C++ 我可以使用部分数据作为锁吗?
我有一个大的数据数组(3e9个元素),我正在多个线程中更新它的值。我刚发现有比赛条件 我认为没有必要锁定整个功能,因为元素彼此独立,可以同时安全地更新C++ 我可以使用部分数据作为锁吗?,c++,multithreading,gcc,compare-and-swap,C++,Multithreading,Gcc,Compare And Swap,我有一个大的数据数组(3e9个元素),我正在多个线程中更新它的值。我刚发现有比赛条件 我认为没有必要锁定整个功能,因为元素彼此独立,可以同时安全地更新数据[1]和数据[234] 我还发现data[]中每个元素的最高有效位永远不会被使用。在该位上实现GCC原子内置锁安全吗 我的代码如下所示,但似乎它正在陷入死锁 const unsigned short LOCK_MASK = 1<<15; unsigned short * lock = &(data[position]);
数据[1]
和数据[234]
我还发现data[]
中每个元素的最高有效位永远不会被使用。在该位上实现GCC原子内置锁安全吗
我的代码如下所示,但似乎它正在陷入死锁
const unsigned short LOCK_MASK = 1<<15;
unsigned short * lock = &(data[position]);
unsigned short oldLock, newLock;
//lock
do {
oldLock = *lock;
newLock = oldLock ^ LOCK_MASK;
} while ((oldLock & LOCK_MASK) || !__sync_bool_compare_and_swap(lock, oldLock, newLock));
//update data[position] here
...
...
...
//unlock
*lock ^= LOCK_MASK;
const unsigned short LOCK\u MASK=1您的代码包含许多数据争用,包括oldLock=*LOCK
和解锁位*LOCK^=LOCK\u MASK
,
由于没有发布障碍,无法将您的更新同步到其他核心
请注意,除了为写入访问锁定阵列段外,还需要为读取访问锁定该段,因为读取和写入必须同步
在该位上实现GCC原子内置锁安全吗
如果要表示读写访问的单独状态(解锁、读锁定x N、写锁定),则需要多个位。
单个位将锁定限制为锁定和解锁两种状态,根据您的代码,可以通过以下方式实现:
const unsigned short LOCK_MASK = 1<<15;
void lock_array_segment(int position)
{
unsigned short *lock = &data[position]; // global array
unsigned short oldLock, newLock;
do {
oldLock = __atomic_load_n (lock, __ATOMIC_RELAXED);
newLock = oldLock | LOCK_MASK; // set bit
} while ((oldLock & LOCK_MASK) || !__sync_bool_compare_and_swap(lock, oldLock, newLock));
}
void unlock_array_segment(int position)
{
unsigned short *lock = &data[position]; // global array
unsigned short oldLock, newLock;
oldLock = __atomic_load_n (lock, __ATOMIC_RELAXED);
newLock = oldLock & ~LOCK_MASK; // clear bit
__atomic_store_n (lock, newLock, __ATOMIC_RELEASE);
}
<代码> const un签署短锁掩码=1 ,您应该考虑更多的标准锁定方式(或更好)。< /P>
也许可以从阅读一些开始(至少是这里解释的概念)
关于C++的阅读。
你可以试探性地考虑对每个连续1024(或其他两个幂)元素的每个段都有一个互斥体。
你可以考虑一种方法。
在获取锁之前,所有的读取都需要同步。特别是,oldLock=*lock代码>是错误的,需要是原子的。目前,如果(oldLock&lock\u MASK)
一次为真,优化器可能会假设*lock
永远不会更改。更保守的方法可能是分配适当数量的实际互斥锁(或自旋锁或任何您希望使用的机制)并使用它们来同步对数据的访问。e、 g.如果您有一个M个互斥体的数组,那么在读取或写入数据数组中的值#i之前,只需让每个线程锁定互斥体#(i%M)。调整M的值,直到找到它的最小值,在该值中,互斥体的争用仍然很少。我以前不知道_atomic*指令!谢谢