Reputation: 7895
A class member function will use a mutex
and lock_guard
on its critical section
or critical data
. I can see that this can be done in 2 different ways.
Case 1: - Inside of for loop. lock_guard
is constructed and destructed on each iteration.
std::mutex s_mutex;
class Foo {
public:
void bar() {
for ( ... ) {
std::lock_guard<std::mutex> guard( s_mutex );
// critical section data
} // lock_guard goes out of scope and releases or unlocks mutex
}
};
Case 2: - Outside of for loop. lock_guard
is created once and then destroyed after loop completes.
std::mutex s_mutex;
class Foo {
public:
void bar() {
std::lock_guard<std::mutex> guard( s_mutex );
for ( ... ) {
// data
}
} // lock_guard goes out of scope releasing or unlocking mutex.
};
I do know that in the first case one thread can access the loop on one iteration while a different thread can access the loop on a different iteration, but no two threads can simultaneously access the critical section. And as for the second case I do know that if a thread is accessing the loop, a second thread can not touch that loop until it finishes fully.
Is one method more desirable over the other or does it depend on the intention of use? Is there a performance impact one over the other? Just want some clarification for trying to maintain modern c++ best practices.
Upvotes: 0
Views: 1141
Reputation:
You are unlocking the mutex to lock it immediately afterwards. What happens depends on how mutex is implementated, but typical non-fair implementation will awake one waiting thread, but will grab the mutex before that thread is able to run, wasting execution time.
If your mutex implementation is fair (think of ticket lock), then your thread won't be able to lock the mutex after unlocking it and will have to wait until another thread leaves the critical section. That means under contention your thread will have to do a context switch at every iteration, wasting execution time.
So the second case (mutex outside the loop) should be more efficient with both fair and non-fair mutex implementation and this is what you should do.
Now you might consider locking the mutex at every iteration if you care about latency, as this allows other threads to run, but this only makes sense with fair mutex implementation.
C++ does not say anything about whether std::mutex
is fair or not and most implementations are not fair. So don't expect much from it.
So the only sane and portable way is to put the lock outside the loop. Because even if you care about latency, std::mutex
is not something that can help you.
Upvotes: 5