Edmund
Edmund

Reputation: 737

Static std::mutex in templated function doesn't work

I have a program like this.

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

using namespace std;

template<int Thread>
void run()
{
    for(int j=0;j<5;++j)
    {
        static std::mutex m;
        m.lock();
        cout<<"Thread "<<Thread<<" running... "<<j<<endl;
        m.unlock();

        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

int main(int argc , char * argv [])
{
    std::thread t1(run<1>);
    std::thread t2(run<2>);

    t1.join();
    t2.join();

    return 0;
}

There is a staic mutex in run()to make sure cout will be executed exclusively. Howerver, when I run this program with visual studio 2012, the output is:

Thread Thread 2 running... 01
 running... 0
Thread 1 running... 1
Thread 2 running... 1
Thread 1 running... 2
Thread 2 running... 2
Thread 2 running... 3
Thread 1 running... 3
Thread 1 running... 4
Thread 2 running... 4

It looks the mutex does not work as expected for the first loop in run(). Did I make anything wrong with the program?

Upvotes: 1

Views: 1765

Answers (4)

utnapistim
utnapistim

Reputation: 27365

This is not a problem with std::mutex. Your run function declares two static mutexes, and locks one for each thread.

Consider declaring the mutex in main and passing it as a parameter to the function, declaring it globally and locking it in the run function, or making the run function a non-template function.

Upvotes: 1

jcoder
jcoder

Reputation: 30035

You have a different mutex in each instantiation of your template. You'll need to make the mutex a global variable or otherwise arrange to use the same one in each function generated from the template.

Upvotes: 1

user1284631
user1284631

Reputation: 4606

You should place the line:

static std::mutex m;

outside the body of run(). For example, declare it global, on the same level as run().

Since you are using a template, two different run() functions are constructed, each one with its own mutex m, invisible to each other.

Upvotes: 2

Stephan Dollberg
Stephan Dollberg

Reputation: 34538

The problem you are facing comes from the fact that your function is a template and such run<1> and run<2> are not the same and such do not share the same static object.

The solution would be to pass your thread number as an argument to your function.

Upvotes: 3

Related Questions