Jack Zhang
Jack Zhang

Reputation: 25

What is the scope of std::mutex object?

Here is the sample code:

#include <iostream>
#include <thread>
#include <mutex>

int value = 0;

void criticalSection(int changeValue)
{
    std::mutex mtx;
    std::unique_lock<std::mutex> uniqueLock(mtx);
    value = changeValue;
    std::cout << value << std::endl;
    uniqueLock.unlock();
    uniqueLock.lock();
    ++value;
    std::cout << value << std::endl;
}

int main(int argc, char **argv)
{
    std::thread t1(criticalSection, 1), t2(criticalSection, 2);
    t1.join();
    t2.join();

    return 0;
}

My question is: what is the scope of mtx in the above code? Will each thread create a mtx within that thread? Is there any difference if I specify mtx as a global variable instead of a local variable?

I just started to learn multithread in C++. Thank you very much for your help.

Upvotes: 0

Views: 1375

Answers (2)

Nicol Bolas
Nicol Bolas

Reputation: 473302

The mutex type doesn't change C++ rules on how variables and objects work.

If you declare a non-static variable on the stack, each call to that function will create its own version of that variable. Regardless of which thread it is. These are all separate and distinct objects.

When you lock a mutex, you are locking that object. Other objects of the same type are unrelated to that lock.

To make a mutex useful, both of the pieces of code trying to lock it must be locking the same object. How you accomplish this is ultimately up to your needs.

Upvotes: 1

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122228

There are no special scoping rules for mutexes. Their scope ends on the next }. In your code every call to criticalSection creates a new mutex instance. Hence, the mutex cannot possibly be used to synchronize the two threads. To do so, both threads would need to use the same mutex.

You can pass a reference to a mutex to the function:

#include <iostream>
#include <thread>
#include <mutex>

int value = 0;

void criticalSection(int changeValue,std::mutex& mtx)
{
    std::unique_lock<std::mutex> uniqueLock(mtx);
    //...
}

int main(int argc, char **argv)
{
    std::mutex mtx;
    std::thread t1(criticalSection, 1,std::ref(mtx)), t2(criticalSection, 2,std::ref(mtx));
    t1.join();
    t2.join();

    return 0;
}

Alternatively you could use a std::atomic<int> value; and drop the mutex when value is the only shared state.

Upvotes: 1

Related Questions