#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;
}
Output:
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
When I call the func function from ThreadLessons class, as seen in output, Number 1, Number 2 and Number 3 output to std::cout is not deterministic like it should be when using a mutex on which a lock was acquired. Notice how Number 4, Number 5 and Number 6 is deterministic and in sequence
Why would it not work for mutex defined in a function inside a class?
Tried using std::cout as a shared resource and expected that it would be used as one when being used from inside a function of a class that locks the mutex
std::thread t1(&ThreadLessons::func, t, "Number 1");
std::thread t2(&ThreadLessons::func, t, "Number 2");
std::thread t3(&ThreadLessons::func, t, "Number 3");
In C++ when you pass something to a function, the object is passed by value. This effectively means that a copy of the object is made.
Here, what ends up happening is three copies of the original object is made. Each call to std::thread
's constructor copies t
, and each thread has its own object and its own mutex.
You had to override the copy constructor before this could compile, since std::mutex
is not copyable. That should've been a big, red, honking clue: copies are being made here.
Instead, std::thread
has a useful overload that takes a pointer to the object, instead:
std::thread t1(&ThreadLessons::func, &t, "Number 1");
std::thread t2(&ThreadLessons::func, &t, "Number 2");
std::thread t3(&ThreadLessons::func, &t, "Number 3");