具有模板化类成员函数的多线程

Multithreading with templated class member function

本文关键字:成员 函数 多线程      更新时间:2023-10-16

所以,我对STL提供的c++ 11并发编程功能相当陌生,我正在玩以下代码:

    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <list>
    using namespace std;
    template <typename T>
    class Container
    {
        private:
            mutex mu;
            list<T> myList;
        public:
            void add(T element)
            {
                lock_guard<mutex> lock1(mu);
                myList.emplace_back(element);
            }
            void remove()
            {
                lock_guard<mutex>lock2(mu);
                myList.pop_back();
            }
            void print()
            {
                for(const auto & element : myList)
                {
                    cout << element << endl;
                }
            }
    };
    int main()
    {
        Container<int> c;
        thread t1(&Container<int>::add, c, 5); //ERROR
        thread t2(&Container<int>::add, c, 10); //ERROR
        thread t4(&Container<int>::remove, c); //ERROR
        thread t5(&Container<int>::remove, c); //ERROR
        t1.join();
        t2.join();
        t4.join();
        t5.join();
        c.print();
    }

当我试图编译我的代码时,我标记为"ERROR"的行导致编译器告诉我:

error: call to implicitly-deleted copy constructor of
  'typename decay<Container<int> &>::type' (aka 'Container<int>')
return _VSTD::forward<_Tp>(__t);
error: no matching constructor for initialization of
  '__tuple_leaf<1UL, Container<int> >'
        __tuple_leaf<_Uf, _Tf>(_VSTD::forward<_Up>(__u))...,
error: no matching function for call to '__decay_copy'
                            __decay_copy(_VSTD::forward<_Args>(__args))...));
                            ^~~~~~~~~~~~

现在,当我在写代码的时候,我已经看了这个问题和这个问题,但是我仍然遗漏了一些小细节。如果有人能提供一些帮助,那就太好了。谢谢!

thread需要复制其所有参数,而您的Container是不可复制的。它是不可复制的,因为它的一个成员(std::mutex)是不可复制的。解决这个问题的方法不是直接给thread c,而是给它一些它可以复制的东西。

:

    thread t1(&Container<int>::add, &c, 5);

下面的代码应该也能工作,但也可能不行(参见T.C.的评论):

    thread t2(&Container<int>::add, std::ref(c), 10);

请注意,这不是为您编译的,这是一件好事,因为否则您的线程将在容器的不同副本上执行工作-而不是像您可能期望的那样仅在一个副本上执行工作。