C++ 我可以使用部分数据作为锁吗?

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]);

我有一个大的数据数组(3e9个元素),我正在多个线程中更新它的值。我刚发现有比赛条件

我认为没有必要锁定整个功能,因为元素彼此独立,可以同时安全地更新
数据[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*指令!谢谢