将线程放入旋转锁中的方法

时间:2013-10-03 13:15:30

标签: c++ multithreading c++11 mutex condition-variable

我想编写一个自定义互斥锁,这样每个线程都可以提供一个参数来表示当前线程想要执行的操作的复杂性。如果操作的复杂性很低,其他线程将像循环锁一样处于循环中,但如果操作的复杂性为中等,则每个线程将迭代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在条件变量上调用notify。现在thread2将一直睡眠,直到另一个线程锁定此互斥锁,然后在其上调用unlock。

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

另一个问题:我的原子操作是否正确排序?

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

1 个答案:

答案 0 :(得分: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吗? (我怀疑是否为此发布新问题)