我正在从我的大学开始练习基于阵列的排队锁的实现。
我的问题如下:如果负责给每个等待线程各自位置的tail
变量溢出,会发生什么?我不是指tail
变量超过数组的大小,我说的是溢出为整数。
使用mod,只要尾部没有溢出,就可以找到线程必须在数组中的正确位置。一旦它溢出,使用mod就可能指向已被占用的位置,或者它可能导致在前一个尾元素未使用之后离开下一个位置,从而使得线程无法连续解锁阵列并且具有正常执行。
有关解决此事的任何建议吗?
答案 0 :(得分:-1)
我认为,设定的线程数计算tail
的最大值,当没有问题时,即当tail
为tail mod num_threads
时最大0
。然后,如果tail
成功,请将tail设置为0
在构造函数中我确定tail
for(unsigned i = UINT32_MAX; ; --i) // UINT32_MAX - max unsigned type value
if(i % size == 0)//size - max number of concurrent threads
{
max_tail = i;
break;
}
并在lock
方法中检查
unsigned max = max_tail;//otherwise, may overwrite max_tail
tail.compare_exchange_strong(max, 0);
完整代码(C ++ 17)
class arr_lock
{
std::atomic<unsigned> tail;
static thread_local unsigned slotInd;
bool* flag;
unsigned size;//max number of concurrent threads
static constexpr size_t L1_cache = std::hardware_destructive_interference_size;
static constexpr size_t mult = L1_cache / sizeof(bool);
unsigned max_tail;
public:
arr_lock(unsigned size_) :
tail(0),
size(size_),
{
unsigned arr_size = mult * size;//padded for disable false sharing
flag = new bool[arr_size];
for(unsigned i = 0; i < arr_size; ++ i)
flag[i] = false;
flag[0] = true;
for(unsigned i = UINT32_MAX; ; --i)
if(i % size == 0)
{
max_tail = i;
break;
}
}
~arr_lock()
{
delete [] flag;
}
void lock()
{
unsigned max = max_tail;//otherwise, may overwrite max_tail
tail.compare_exchange_strong(max, 0);
unsigned slotInd = tail.fetch_add(1) % size;
unsigned ind = mult * slotInd;
while(!flag[ind]);
}
void unlock()
{
flag[mult * slotInd] = false;
flag[mult * (slotInd + 1) % (mult * size)] = true;
}
};
thread_local unsigned arr_lock::slotInd = 0;