c++ 在main中的线程中调用类内定义的函数时,该函数中使用的互斥锁似乎不起作用

plicqrtu  于 2023-02-10  发布在  其他
关注(0)|答案(2)|浏览(168)
#include <thread>
#include <iostream>
#include <mutex>

class ThreadLessons {
private:
    std::mutex _threading_mutex_in_class;
public:
    ThreadLessons() {}
    ThreadLessons(const ThreadLessons &tl) {}
    ThreadLessons operator=(const ThreadLessons &tl) {return *this;}
    
    void func(std::string s) {
        std::unique_lock lg(_threading_mutex_in_class);
        std::cout << std::endl;
        for(int i{0}; i<10; i++) {
            std::cout << s << std::endl;
        }
    }
};

std::mutex _threading_mutex;

void func(std::string s) {
    std::unique_lock lg(_threading_mutex);
    std::cout << std::endl;
    for(int i{0}; i<10; i++) {
        std::cout << s << std::endl;
    }
}

int main()
{
    std::cout << "Starting threading of function from another class in same file" << std::endl;
    ThreadLessons t;
    std::thread t1(&ThreadLessons::func, t, "Number 1");
    std::thread t2(&ThreadLessons::func, t, "Number 2");
    std::thread t3(&ThreadLessons::func, t, "Number 3");

    t1.join();
    t2.join();
    t3.join();
    
    std::cout << "Starting threading of function from main" << std::endl;
    std::thread t4(func, "Number 4");
    std::thread t5(func, "Number 5");
    std::thread t6(func, "Number 6");

    t4.join();
    t5.join();
    t6.join();
    
    return 0;
}

输出:

Starting threading of function from another class in same file

Number 1
Number 1
Number 1
Number 2
Number 2
Number 2

Number 3
Number 3
Number 1Number 2
Number 2
Number 3
Number 3Number 1

Number 2
Number 1Number 3Number 2

Number 2
Number 3
Number 3
Number 1
Number 1
Number 2
Number 1Number 3

Number 2
Number 1
Number 3
Number 3
Starting threading of function from main

Number 4
Number 4
Number 4
Number 4
Number 4
Number 4
Number 4
Number 4
Number 4
Number 4

Number 5
Number 5
Number 5
Number 5
Number 5
Number 5
Number 5
Number 5
Number 5
Number 5

Number 6
Number 6
Number 6
Number 6
Number 6
Number 6
Number 6
Number 6
Number 6
Number 6

当我从ThreadLessons类调用func函数时,如输出中所示,输出到std::cout的1号、2号和3号输出不像使用获取锁的互斥锁时那样具有确定性。
为什么它不适用于类内函数中定义的互斥锁?
已尝试将std::cout用作共享资源,并希望在锁定互斥锁的类的函数内部使用时将其用作共享资源

vsmadaxz

vsmadaxz1#

std::thread t1(&ThreadLessons::func, t, "Number 1");
std::thread t2(&ThreadLessons::func, t, "Number 2");
std::thread t3(&ThreadLessons::func, t, "Number 3");

在C++中,当你传递一个东西给一个函数时,这个对象是***传值的,这实际上意味着这个对象被复制了。
在这里,最终发生的是原始对象的三个副本。每次调用std::thread的构造函数都会复制t,每个线程都有自己的对象和互斥体。
因为std::mutex是不可复制的,所以在编译之前必须重写复制构造函数,这应该是一个很大的红色提示:正在这里复印。
相反,std::thread有一个有用的重载,它接受一个指向该对象的指针:

std::thread t1(&ThreadLessons::func, &t, "Number 1");
std::thread t2(&ThreadLessons::func, &t, "Number 2");
std::thread t3(&ThreadLessons::func, &t, "Number 3");
t30tvxxf

t30tvxxf2#

当你把t传递给线程构造函数时,会产生一个副本,类的每个示例都有自己的互斥锁,一个互斥锁只被一个线程使用是相当无用的。
对于free函数,每次调用该函数都使用同一个互斥锁。
要通过引用传递对象,可以使用std::ref

std::thread t1(&ThreadLessons::func,std::ref(t), "Number 1");

实际上还是做了一个拷贝,但是拷贝是std::reference_wrapper的,它 Package 了t,并且作为一个引用,实际上就好像t是通过引用传递的一样。

相关问题