Reputation: 71
I am a newbie in Threading in C++. I need your help regarding usage of mutex
and lock_guard
(this part doesn't matter). I have a main function and a secondary functions.
Please tell me why multithreading doesn't work when I add lock_guard(mtx)
;
When I remove it, it runs faster but wrongly. Can you help me with it?
I need a correct access to the vector vec
and enabling threading.
#include <vector>
#include <thread>
std::mutex mtx;
void threadCall(std::vector<int> &vec, int start, int end){
std::lock_guard<std::mutex> guard(mtx);
for(int i=start; i<end; i++)
vec[i] = i;
}
void ThreadFunc(std::vector<int> vec){
std::vector<std::thread> threads(2);
threads[0] = std::thread(&threadCall, std::ref(vec), 0, 10);
threads[1] = std::thread(&threadCall, std::ref(vec), 10, 20);
threads[0].join();
threads[1].join();
}
int main(){
std::vector<int> vec(20);
ThreadFunc(vec);
return 0;
}
Upvotes: 1
Views: 7802
Reputation: 170203
To start with, stop passing the vector by value, pass references. After that is resolved, your particular example doesn't need a mutex at all, actually. Your vector has a fixed size:
std::vector<int> vec(20);
And all elements are default constructed from the get go. Since all you do is assignment:
vec[i] = i;
The vector won't reallocate any storage or adjust its item count. So there's no need to lock access to the vector as a whole. Couple that with the fact that each thread operates on a separate sub-range, and there aren't any data races present. You don't need synchronization primitives.
Upvotes: 4
Reputation: 10126
The problem is that mutex is taken by the first thread and second thread can't work until it's released.
So, essentially you receive a multi-threaded application that where all threads do their job serially.
You can move your guard into for-loop
for(int i=start; i<end; i++) {
std::lock_guard<std::mutex> guard(mtx);
vec[i] = i;
}
That will give threads a possibility to work together over the passed vector.
BUT:
You need to take into account that multiple threads not always give a performance boost jut because concurrency != parallelism.
I would expect from this application in this way be actually slower than a single-threaded implementation because the following:
mutex
so only one thread runs at timeSOLUTION IDEA:
If you want to run it truly parallel, you need to make threads work on independent data and then join the result.
Upvotes: 4
Reputation: 15334
The mutex is preventing the threads from doing any work in parallel. As long as you can guarantee that each thread is not going to write to the same part of the vector you don't need the mutex at all.
The other problem is you are passing your vector by value. You should instead pass by reference:
void threadCall(std::vector<int>& vec, int start, int end){
for(int i=start; i<end; i++)
vec[i] = i;
}
void ThreadFunc(std::vector<int>& vec){
std::vector<std::thread> threads(2);
threads[0] = std::thread(&threadCall, std::ref(vec), 0, 10);
threads[1] = std::thread(&threadCall, std::ref(vec), 10, 20);
threads[0].join();
threads[1].join();
}
int main(){
std::vector<int> vec(20);
ThreadFunc(vec);
}
Upvotes: 5