2线程同步,无需手动mutex.lock()

问题描述 投票:0回答:1

我有 2 个线程,
一个线程创建一个管道并对其负责,
另一个线程创建该管道与外部世界的通信,
所以我想在管道初始化后创建通信。
这段代码可以工作,但是:

  • 互斥体有一个警告:
    C26110 Caller failing to hold lock 'm' before calling function 'std::_Mutex_base::unlock'
    ,它是关于什么的?
  • 如何在不手动互斥操作的情况下重写它?

#include <iostream>
#include <mutex>

using namespace std::chrono_literals;

class Pipeline {
public:
    Pipeline() { std::cout << "Pipeline()\n"; };
    void init() { std::cout << "Pipeline::init()\n"; std::this_thread::sleep_for(3s); };
    void run() { while (true) { std::cout << "Pipeline::run()\n"; std::this_thread::sleep_for(1s); } };
};

class Connection {
public:
    Connection(Pipeline* p) { std::cout << "Connection()\n"; };
    void run() { while (true) { std::cout << "Connection::run()\n"; std::this_thread::sleep_for(1s); } };
};

void pipeline_func(Pipeline** pipeline, std::mutex& m) {
    *pipeline = new Pipeline();
    (*pipeline)->init();

    m.unlock();

    (*pipeline)->run(); // run indefinitely
};


void connection_func(Pipeline** pipeline, std::mutex& m) {
    m.lock();

    Connection connection(*pipeline);
    connection.run(); // run indefinitely
};


int main() {
    Pipeline* pipeline = nullptr;

    std::mutex m;
    m.lock(); // lock there for stopping connection3_thread, intil mutex is unlocked in pipeline_thread

    std::thread pipelineTh(pipeline_func, &pipeline, std::ref(m));
    std::thread connectionTh(connection_func, &pipeline, std::ref(m));

    pipelineTh.join();
    connectionTh.join();

    m.unlock();
}
c++ multithreading mutex thread-synchronization
1个回答
0
投票

如果你想完全避免互斥体,我建议使用原子,但是如果你处理多个线程,原子可能很难使用,因为它们不能放入标准向量类中,所以你将不得不求助于非常可怕的手册堆分配。

除此之外,您还可以使用可以实现的作用域锁来促进互斥体的管理:作用域锁定如何工作?.

此外,我想指出,在您当前的代码中,您在connection_func()函数中调用m.lock(),但之后您没有调用解锁(在同一范围内),因此您可能会遇到线程锁定,所以我会避免编写在函数内调用互斥锁但在函数外部解锁互斥锁的代码,因为这可能会导致上述情况。这是使用作用域锁的一个很好的理由,因为您将能够保护代码的关键部分,而不必担心稍后解锁互斥体。

© www.soinside.com 2019 - 2024. All rights reserved.