2

我想编写一个自定义互斥锁,这样每个线程都可以提供一个参数,该参数表示当前线程想要执行的操作的复杂性。如果操作的复杂性很低,其他线程将像自旋锁一样处于循环中,但如果操作的复杂性中等,每个线程将迭代 50 次,然后将按条件变量休眠,如果操作非常复杂,其他线程将直接去睡觉。

    enum LockOperation
    {
        LockOperation_Light = -1,
        LockOperation_Medium = 50,
        LockOperation_Heavy = 1
    };

    class CustomMutex
    {
    private:

    protected:
        std::atomic<int> mFlag;
        std::mutex mMutex;
        std::condition_variable mCond;

    public:
        CustomMutex() { std::atomic_init(&mFlag, 0); };
        ~CustomMutex() {};

        void lock(LockOperation pLockOperation = LockOperation_Medium) 
        {
            int lNewLoopCount = static_cast<int>(pLockOperation);
            int lLoopCounter = 0;
            int lExpected = 0;
            int lLoopCount = std::atomic_load_explicit(&mFlag, std::memory_order_relaxed); 

            while (true)
            {
                while(std::atomic_load_explicit(&mFlag, std::memory_order_relaxed) != 0 && 
                      lLoopCounter != lLoopCount)
                    ++lLoopCounter;
                std::atomic_compare_exchange_strong_explicit(
                    &mFlag, 
                    &lExpected,
                    lNewLoopCount,
                    std::memory_order_acquire,
                    std::memory_order_relaxed);
                if(lExpected == 0)
                {
                    return;
                }
                else if(lLoopCounter == lLoopCount)
                {
                    lExpected = 0;
                    std::unique_lock<std::mutex> lGuard(mMutex);
                    mCond.wait(lGuard);
                }
                else
                {
                    lExpected = 0;
                    continue;
                }
            }
        };
        bcInline void UnLock() 
        { 
            std::atomic_store_explicit(&mFlag, 0, std::memory_order_relaxed);
            std::lock_guard<std::mutex> lGuard(mMutex);
            mCond.notify_one();
        };
    };

现在假设 thread1 锁定了这个互斥体,并且 thread2 等待由于它的 loopCounter 到达它的结尾并且在锁定条件变量的互斥体之前,thread1 调用条件变量上的通知。现在 thread2 将休眠,直到另一个线程锁定此互斥体,然后对其调用 unlock。

我是多线程新手,我想学习。我知道我的课程可能包含错误或可能完全错误,但有没有办法纠正这个问题或编写这样一个互斥锁的好算法。

另一个问题:我的原子操作顺序正确吗?

(对不起,如果我的问题有点模棱两可,我的英语不好)

4

1 回答 1

0

我想如果我改变第二个如果:

else if(lLoopCounter == lLoopCount)
{
    lExpected = 0;
    std::unique_lock<std::mutex> lGuard(mMutex);
    mCond.wait(
        lGuard, 
        [&]()->bool { return std::atomic_load_explicit(&mFlag, std::memory_order_relaxed) == 0; });
}

并解锁:

std::lock_guard<std::mutex> lGuard(mMutex);
std::atomic_store_explicit(&mFlag, 0, std::memory_order_relaxed);
mCond.notify_one();

问题会解决

现在为了优化,我可以从解锁方法中删除 lGuard 并将 std::memory_order_relaxed 更改为 std::memory_order_release 吗?(我怀疑是否为此发布新问题)

于 2013-10-03T20:35:08.397 回答