c++ - 具有两个排他锁组的共享锁

标签 c++ locking mutex semaphore

我有两种不应该同时执行的方法“记录”和“测量”。
因此,我尝试使用“std::mutex”来执行以下操作:

void log(std::string message)
{
    mtx.lock();
    someLogFunctionality();
    mtx.unlock();
}

void measure()
{        
    mtx.lock();
    someMeasureFunctionality();
    mtx.unlock();
}
现在事实证明,也可以在不锁定的情况下并行多次调用“log”,这同样适用于“measure”。 (原因: someLogFunctionality() 和 someMeasureFunctionality() 相互干扰,但同一方法可能会被多次并行调用)
然后我查看了“std::shared_mutex”,但对我来说有两个问题:
1.) 使用 shared_mutex 我只能将 lock_shared 用于其中一种方法(日志或度量),但另一个方法必须使用排他锁(并且不能再次并行执行多次)
void log(std::string message)
{
    mtx.lock_shared();
    someLogFunctionality();
    mtx.unlock_shared();
}

void measure()
{        
    mtx.lock(); // This should also be shared but among another "group"
    someMeasureFunctionality();
    mtx.unlock();
}
2.) 我不能使用 C++17(我正在使用的环境中的约束)
你对我如何实现这一点有什么建议吗?

最佳答案

根据 alexb 的回复,我编写了以下当前对我有用的互斥类(到目前为止仅在一个简单的多线程示例应用程序中尝试过)
请注意,它不受“饥饿”保护。简而言之:如果 lockLogging 被频繁调用(反之亦然),则不能确保该 lockMeasure 将永远获得锁定。

class MyMutex
{
private:
    std::atomic<int> log_executors;
    std::atomic<int> measure_executors;

    std::mutex mtx;
    std::condition_variable condition;

public:
    MyMutex() : log_executors(0), measure_executors(0) {}
    
    ~MyMutex() {}

    void lockMeasure()
    {   
        std::unique_lock<std::mutex> lock(mtx);

        while(log_executors) {
            condition.wait(lock); 
        }
        measure_executors++; 
    }
    
    void unlockMeasure()
    {   
        std::unique_lock<std::mutex> lock(mtx);

        measure_executors--; 
        if (!measure_executors)
        {
          condition.notify_all();
        }
    }
    
    void lockLogging()
    {         
        std::unique_lock<std::mutex> lock(mtx);

        while(measure_executors) {
          condition.wait(lock); 
        }
        log_executors++;
    }

    void unlockLogging()
    {         
        std::unique_lock<std::mutex> lock(mtx);

        log_executors--; 
        if (!log_executors)
        {
          condition.notify_all(); 
        }
    }

    static MyMutex& getInstance()
    {
        static MyMutex _instance;
        return _instance;
    }    
};
用法:
void measure()
{
    MyMutex::getInstance().lockMeasure();

    someMeasureFunctionality();

    MyMutex::getInstance().unlockMeasure();
}

void log()
{
    MyMutex::getInstance().lockLogging();

    someLogFunctionality();

    MyMutex::getInstance().unlockLogging();
}

关于c++ - 具有两个排他锁组的共享锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62758453/

相关文章:

go - 带 ttl 的 etcd 互斥锁

c++ - 没有用于初始化 std::lock_guard<std::mutex> 的匹配构造函数

qt - MinGW 64(posix 线程版本)中 std::mutex 和 QMutex 的性能

c++ - 找不到句首

c# - 使用 .Net 缓存时应该添加 Locks 还是 TransactionScope?

c++ - 什么时候调用构造函数?

python - Lock.acquire(False) 可以吗?

c++将unique_ptr作为对另一个函数的引用传递

c++ - 使用 mxGetPr 与 mxGetData

c++ - <sizeof(T)> 作为 C++ 中的继承类模板参数