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

Ensuring mutex lock is called before unlock

试图仅在互斥量被锁定时执行一段代码。 class mainclass 中的方法仅在互斥量被锁定时执行任务。为避免在未锁定的情况下解锁互斥锁时产生未定义的行为(考虑锁定可能失败的情况),使用 mutexclass.

的构造函数和析构函数处理锁定和解锁

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

#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;
}

您设置了一个布尔值来指示互斥体是否被锁定。您还可以检查 class:

之外的值
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,它会在出错时抛出异常。

你真的应该使用 std::mutex and std::lock_guard, and in general the 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.
    }
}