我执行std :: lock时出现总线错误

时间:2019-05-10 04:19:36

标签: c++ c++17

我正在尝试实现std::lock。策略是try_lock()每个互斥锁,如果失败,我将解锁所有锁定的互斥锁并从下一个互斥锁开始。运行此代码时,我得到Bus Error: 10(尽管并非总是如此)。我无法理解我要去哪里。

使用gcc和clang编译-结果相同。

代码:

#include <iostream>
#include <string>
#include <mutex>
#include <thread>

using namespace std;
int counter = 0;
std::mutex m1,m2,m3;

//base case
template <typename T>
void unlock_all(T& obj)
{
    obj.unlock();
}

// just keep unlocking!
template<typename T, typename... Args>
void unlock_all(T& obj, Args&... rest)
{
    obj.unlock();
    unlock_all(rest...);
}


template <typename T>
void unlock_last(T& obj)
{
    obj.unlock();
}

template <typename T, typename... Args>
void unlock_last(T& obj, Args&... rest)
{
    if(counter == sizeof...(rest))
    {
        unlock_all(rest...);
        return;
    }
    else
    {
        unlock_last(rest...);
    }

}

template <typename T, typename... Args>
void lock_all(T& obj, Args&... rest)
{

    if(counter == (1 + sizeof...(rest)))
    {
        cout << "all locked!" << endl;
        //unlock all now
        unlock_all(rest...,obj);
        return;
    }

    if(obj.try_lock())
    {
        counter++;
        lock_all(rest...,obj);
    }
    else
    {
        // Here, if counter is NOT 0, we should unlock all the locks we have locked earlier and
        // try to lock from the next lock in line. We can use counter to find the 
        // locks that are locked.
        if(counter == 0)
        {
            lock_all(rest...,obj);
        }
        else
        {
            unlock_last(rest...);
            counter = 0;
        lock_all(rest...,obj);
        }
    }
}

void func1()
{
    m1.lock();
    cout << "THREAD 1 printing " << endl;
    m1.unlock();
}
void func2()
{
    m2.lock();
    cout << "THREAD 2 printing " << endl;
    m2.unlock();
}
void func3()
{
    m3.lock();
    cout << "THREAD 3 printing " << endl;
    m3.unlock();
}

void func()
{
    lock_all(m1,m2,m3);
}
int main()
{

    std::thread t1(func1);
    std::thread t2(func2);
    std::thread t3(func3);
    std::thread t4(func);

    t1.join();
    t2.join();
    t3.join();
    t4.join();

}

不太确定该如何调试。代码非常简单;我在这里可以做什么?花了几天时间,却没有任何进展。

1 个答案:

答案 0 :(得分:2)

unlock_last的可变版本始终假定第一个参数未锁定。因此,在

        unlock_last(rest...);
        counter = 0;
        lock_all(rest...,obj);

如果在输入counter == sizeof...(rest)之前(即,您已锁定除lock_all的第一个参数之外的所有内容),则对unlock_last的调用实际上不会解锁您的所有内容已经锁定。

(我希望这只是一个概念证明,因为同步函数中的可变全局状态只是...不。)