锁定数组的多个部分 - 多线程

时间:2017-01-30 15:47:41

标签: c++ multithreading openmp atomic spinlock

我正在尝试为具有以下预期用例的数组实现线程安全锁定机制:

  1. 请求您要锁定的索引并尝试获取它们。如果你没有获得任何索引,就会纾困,然后再试一次(基本上是旋转)。
  2. 获取必要的锁后,对这些索引执行处理。
  3. 释放获得的锁!
  4. 我正在使用以下代码来测试锁 - 它只是递增测试计数,并为每次迭代指定相同的索引(因此它强制访问是顺序的)。唯一的问题是它不起作用,我有点难过......

    我有一种感觉,我错过了一些关键的竞争条件,但我还不能认同它:(

    #pragma omp parallel for
    for (int i = 0; i < activeItems; i++)
    {
        std::vector<int> lockedBucketIndexes = {0, 1, 2, 3};
        //try and get a lock on the buckets we want, otherwise keep trying          
        while (!spatialHash->TryAcquireBucketLocks(lockedBucketIndexes))
        {
            //TODO - do some fancy backoff here
        }
    
        testCount++;
    
        spatialHash->DropBucketLocks(lockedBucketIndexes);
    }
    

    执行锁定的类/方法:

    std::vector<int> _bucketLocks;
    SpinLock _bucketLockLock;
    
    bool SpatialHash::TryAcquireBucketLocks(std::vector<int> bucketIndexes)
    {
        bool success = true;
        //try and get a lock to set our bucket locks... lockception
        _bucketLockLock.lock();
    
        //quickly check that the buckets we want are free
        for each (int bucketIndex in bucketIndexes)
        {
            if (_bucketLocks[bucketIndex] > 0)
            {
                success = false;
                break;
            }
        }
    
        //if all the buckets are free, set them to occupied
        if (success)
        {
            for each (int bucketIndex in bucketIndexes)
            {
                _bucketLocks[bucketIndex] = 1;
            }
        }
    
        //let go of the lock
        _bucketLockLock.unlock();
    
        return success;
    }
    
    void DropBucketLocks(std::vector<int> bucketIndexes)
    {
        //I have no idea why these locks are required
        //It seems to almost work with them though...
        _bucketLockLock.lock();
    
        for each (int bucketIndex in bucketIndexes)
        {
            _bucketLocks[bucketIndex] = 0;
        }
    
        _bucketLockLock.unlock();
    
        return true;
    }
    

    自旋锁类:

    class SpinLock {
        std::atomic_flag locked = ATOMIC_FLAG_INIT;
    public:
        void lock() {
            while (locked.test_and_set(std::memory_order_acquire)) { ; }
        }
        void unlock() {
            locked.clear(std::memory_order_release);
        }
    }; 
    

0 个答案:

没有答案