确保在解锁之前调用互斥锁

时间:2019-06-19 07:23:13

标签: c++ class mutex

仅当互斥锁被锁定时才尝试执行一段代码。 mainclass类中的方法仅在互斥锁被锁定时才执行任务。为了避免在互斥锁未锁定而未锁定的情况下解锁时(考虑到锁定可能失败的情况),请使用mutexclass的构造函数和析构函数来处理锁定和解锁。

我想在执行来自mainclass方法calling1()calling2()的代码之前检查互斥锁是否被锁定。由于构造函数不会返回值,因此想知道执行此操作的其他方法。

#include <iostream>
using namespace std;

class mutexclass
{
    public:
    pthread_mutex_t *mutex;
    bool a = true;
    mutexclass(pthread_mutex_t* inmutex)
    {   mutex= inmutex;
        int err=pthread_mutex_lock(mutex);
        cout<<"automutex constructor";
        if(err != 0)
        a = false;
    };
    ~mutexclass()
    {
        if(a)
        {
            pthread_mutex_unlock(mutex);
            cout<<"automutex destructor";
        }
        else
            cout<<"a is not true";
    };
};  
class mainclass{
    public:
    mainclass();
    ~mainclass();
    pthread_mutex_t lock;
    void calling1();
    void calling2();
};
mainclass::mainclass()
{
    pthread_mutex_init(&lock,NULL);
}
mainclass::~mainclass()
{
    pthread_mutex_destroy(&lock);
}
void mainclass::calling1()
{
    mutexclass m = mutexclass(&lock);
    //call cout only if mutex lock is successful
    cout<<"calling1";
}
void mainclass::calling2()
{
    mutexclass m = mutexclass(&lock);
    cout<<"calling2";
}

int main() {
    mainclass s;

    s.calling1();
    s.calling2();
    return 0;
}

2 个答案:

答案 0 :(得分:4)

您应该真正使用std::mutexstd::lock_guard,通常使用standard C++ threading support。但是,如果由于某种原因您不能(也许这是一次学习练习?),那么我建议您防止mutexclass处于互斥体未锁定的状态。那应该是一个错误,所以如果无法获取锁,则抛出异常。

防止实例被复制也很重要。否则,同一个互斥锁将在每个副本的析构函数中多次解锁。为避免这种情况,请删除复制构造函数和赋值运算符。

#include <system_error>

class mutexclass
{
public:
    explicit mutexclass(pthread_mutex_t* inmutex)
        : mutex(inmutex)
    {
        int err = pthread_mutex_lock(mutex);
        if (err != 0) {
            throw std::system_error(err, std::generic_category(),
                "pthread mutex lock acquisition failure");
        }
    }

    ~mutexclass()
    {
        pthread_mutex_unlock(mutex);
    }

    mutexclass(const mutexclass&) = delete;
    mutexclass& operator=(const mutexclass&) = delete;

private:
    pthread_mutex_t* mutex;
};

现在您可以像这样实现calling*函数:

void mainclass::calling1()
{
    try {
        mutexclass m(&lock);
        cout << "calling1\n";
    } catch (const std::exception& e) {
        // Could not lock.
    }
}

答案 1 :(得分:1)

您设置了一个布尔值以指示互斥对象是否已锁定。您还可以在课外检查该值:

class mutexclass
{
public:
    mutexclass(pthread_mutex_t* inmutex)
    {   
        mutex = inmutex;
        int err = pthread_mutex_lock(mutex);
        if(err == 0) locked_ = true;
    }
    ~mutexclass()
    {
        if(locked_) {
            pthread_mutex_unlock(mutex);
        }
    }
    bool locked() const { return locked_; }

private:
    pthread_mutex_t *mutex;
    bool locked_ = false;
};  

void mainclass::calling1()
{
    mutexclass m = mutexclass(&lock);
    //call cout only if mutex lock is successful
    if (m.locked()) {
        cout<<"calling1";
    }
}

您还可以使用std::mutex,该错误会引发错误。