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

时间:2014-08-27 08:16:22

标签: c++ multithreading c++11

我正在学习如何在标准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)));
}

2 个答案:

答案 0 :(得分:2)

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

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

请注意,在这种情况下,这并不能真正使用函数。


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

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

答案 1 :(得分:1)

在您的代码中,每个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 ) )) );

}