基于数组的排队锁 - 尾溢出

时间:2016-01-06 14:47:57

标签: arrays locking queue tail integer-overflow

我正在从我的大学开始练习基于阵列的排队锁的实现。

我的问题如下:如果负责给每个等待线程各自位置的tail变量溢出,会发生什么?我不是指tail变量超过数组的大小,我说的是溢出为整数。

使用mod,只要尾部没有溢出,就可以找到线程必须在数组中的正确位置。一旦它溢出,使用mod就可能指向已被占用的位置,或者它可能导致在前一个尾元素未使用之后离开下一个位置,从而使得线程无法连续解锁阵列并且具有正常执行。

有关解决此事的任何建议吗?

1 个答案:

答案 0 :(得分:-1)

我认为,设定的线程数计算tail的最大值,当没有问题时,即当tailtail 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;