What is protecting range of "std::lock_guard"?

I am learning multithread programming in C++. I have a question about :std::lock_guard.

In following example code:

void print_thread_id (int id) {
std::lock_guard<std::mutex> lck (mtx);
print_even(id);
print_even(id+1);
}

When will mtx be unlocked? In line "print_even(id)" or "print_even(id+1)"?
Or ask in more general way, what is protecting range of "std::lock_guard"?

Thank you.

a lock guard locks the mutex when it is constructed and unlocks it when it leaves scope (when the destructor is called). So the protected range is up to the '}' after print_even(id+1).

By the way, the reference pages on this site are excellent.

http://www.cplusplus.com/reference/mutex/lock_guard/
Last edited on
Thank you so much!
One more question. So it locked all the variables (no matter it changed or not) between construct and destruct?

E.g:

void print_thread_id (int id1, int id2) {
std::lock_guard<std::mutex> lck (mtx);
id1++;
print_even(id1);
print_even(id2);
}

So it locked both id1 (modified) and id2 (not modified), correct?

Thank you.

So it locked both id1 (modified) and id2 (not modified), correct?
No. There's no connection between a variable and the mutex.

id1 and id2 are local variables. They don't need protection since no other thread may access them.
Thank you for reply.

Yes, this is not a good example.


void print_thread_id (int & id1, int & id2) {
std::lock_guard<std::mutex> lck (mtx);
id1++;
print_even(id1);
print_even(id2);
}

You mentioned "No. There's no connection between a variable and the mutex. " So then what mutex lock?

Thank you.
In your example the second thread would wait until print_even(id2); is done.

Note that if print_even(...) tries to lock mtx again it will result in a deadlock (since mutex is not recursive).


If you want to protect the variable id1 only you may write it like so:
1
2
3
4
5
6
7
8
void print_thread_id (int & id1, int & id2) {
{ // Note this limits the scope for mtx
std::lock_guard<std::mutex> lck (mtx);
id1++;
} // The execution of the following functions are not protected (which improves parallelism)
print_even(id1);
print_even(id2);
}


Note that a variable needs protection only if it is in fact shared. In your case each thread could provide its own variable which would make the protection useless.

For recrursive call of a mutex:
http://www.cplusplus.com/reference/mutex/recursive_mutex/?kw=recursive_mutex
You mentioned "No. There's no connection between a variable and the mutex. " So then what mutex lock?


A mutex does not actually lock anything except itself. It is used by programmers to isolate critical sections of code so that multiple parallel threads cannot be in a a critical section at the same time. Usually critical sections involve modifying one or more variables that are shared across threads. However, this requires developer intuition--the mutex is not explicitly associated with a variable.

You could have one thread obtain a mutex protecting a variable and have another thread modify that variable without obtaining the mutex. In this case the mutex did not do its job because the programmer failed to identify all of the critical sections of code. In other words, a mutex is a tool used by a developer to protect access to a variable, not a safe access to the variable in and of itself.
Thank you, both of you. Now it seems I have a better understanding. E.g.:

class A
{
private :
int num;
std::mutex mtx;

public:
numPlus()
{
std::lock_guard<std::mutex> lck (mtx);
num++;
}

numMinus()
{
num--;
}

}


In this example, if I run functions numPlus and numMinus in two threads, then the variable "num" will not be protected because numMinus() even doesn't have mtx inside it. So it will modfiy num no matter whether numPlus is excuting or not, correct?

Thank you.
That's right.
Topic archived. No new replies allowed.