c++ 如何将 std::mutex 和 std::lock_guard 与仿函数一起使用?

Posted

技术标签:

【中文标题】c++ 如何将 std::mutex 和 std::lock_guard 与仿函数一起使用?【英文标题】:c++ how to use std::mutex and std::lock_guard with functor? 【发布时间】:2014-08-27 08:16:22 【问题描述】:

我正在学习如何在标准 C++ 中使用std::thread,但我无法用std::mutex 解决一个问题。

我正在运行 2 个线程,它们具有在 CMD 中显示消息的简单函数。我想使用std::mutex,这样一个线程将等到另一个威胁停止使用缓冲区。

当我使用函数时,一切正常,但使用函子时我遇到了问题:

错误 C2280: 'std::mutex::mutex(const std::mutex &)' : 试图引用已删除的函数

我做错了什么?

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

class thread_guard

    private:
        std::thread m_thread;
    public:
        thread_guard(std::thread t)
        
            m_thread = std::move(t);
            if (!m_thread.joinable())
                std::cout << "Brak watku!!!" << std::endl;
        
        ~thread_guard()
        
            m_thread.join();
        
;

class func

    private:
        std::mutex mut;
    public:
        void operator()()
                   
            for (int i = 0; i < 11000; i++)
            
                std::lock_guard<std::mutex> guard(mut);
                std::cout << "watek dziala 1" << std::endl;
            
        
;

class func2

    private:
        std::mutex mut;
    public:
        void operator()()
                   
            for (int i = 0; i < 11000; i++)
            
                std::lock_guard<std::mutex> guard(mut);
                std::cout << "watek dziala 2" << std::endl;
            
        
;

std::mutex mut2;

void fun()
   
    for (int i = 0; i < 11000; i++)
    
        std::lock_guard<std::mutex> guard(mut2);
        std::cout << "watek dziala 1" << std::endl;     
    


void fun2()
   
    for (int i = 0; i < 11000; i++)
    
        std::lock_guard<std::mutex> guard(mut2);
        std::cout << "watek dziala 2" << std::endl;
    


int main(void)

    thread_guard t1( (std::thread( func() )) );
    thread_guard t2( (std::thread(func2() )) );
    //thread_guard t1((std::thread(fun)));
    //thread_guard t2((std::thread(fun2)));

【问题讨论】:

看这个:***.com/questions/21409439/… 该错误表明您正在尝试复制互斥体(调用复制构造函数),这显然是不允许的。 但我对函数做同样的事情,但在课堂上。那么问题出在哪里?? 【参考方案1】:

你实际上有两个问题。编译错误是因为函数对象被复制,但是嵌入的互斥体没有有效的复制构造函数,所以你得到一个错误。相反,您必须创建对象的实例,并传递成员函数和指向该对象的指针:

func f1;
thread_guard t1(std::thread(&func::operator(), &f1));

请注意,在这种情况下使用函数并没有真正的用处。


另一个问题是每个仿函数对象都有自己的互斥锁,因此两个线程将完全独立运行。

例如,如果你将互斥锁设为全局,那么你也解决了第一个问题,并且可以毫无问题地使用仿函数。

【讨论】:

【参考方案2】:

在您的代码中,每个function 都拥有一个互斥锁。这些是不同的互斥体,实际上它们不保护任何东西。

问题是函数必须是可复制的,而互斥体不是。如果函数需要锁定一个互斥锁,它通常是针对某个共享资源的,你可以通过引用你的仿函数来传递这个互斥锁。

在外部创建互斥锁,例如在 main() 中,然后

class func

    std::mutex * mutex;

public:
    explicit func( std::mutex & m ) : mutex( &m )
    
    

    void operator()()
    
      for (int i = 0; i < 11000; i++)
        
            std::lock_guard<std::mutex> guard(*mutex);
            std::cout << "watek dziala 1" << std::endl;
        
         
;

func2 类似

int main(void)

   std::mutex mutex;
   thread_guard t1( (std::thread( func( mutex) )) );
   thread_guard t2( (std::thread( func2( mutex ) )) );

【讨论】:

以上是关于c++ 如何将 std::mutex 和 std::lock_guard 与仿函数一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 C++ 中 std::mutex 的构造函数不抛出?

我可以在 C++ 中仅使用 std::atomic 而不使用 std::mutex 安全地共享一个变量吗?

C++并发编程之二 在线程间共享数据

C++关于锁的总结

C++11:基于std::queue和std::mutex构建一个线程安全的队列

C++ 协议缓冲区:常量表达式中的临时非文字类型 'google::protobuf::internal::CallOnInitializedMutex <std::mutex>'