6

I'm learning about std::mutex, std::thread and I am surprised at the different behavior of 2 pieces of code below:

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;

std::mutex mtx;

void foo(int k)
{
    std::lock_guard<std::mutex> lg{ mtx };
    for (int i = 0; i < 10; ++i)
        cout << "This is a test!" << i << endl;
    cout << "The test " << k << " has been finished." << endl;
}

int main()
{
    std::thread t1(foo, 1);
    std::thread t2(foo, 2);
    t1.join();
    t2.join();
    return 0;
}

The output is sequential. But if I donot name variable std::lock_guard<std::mutex>, the output is unordered

void foo(int k)
{
    std::lock_guard<std::mutex> { mtx }; // just erase the name of variable
    for (int i = 0; i < 10; ++i)
        cout << "This is a test!" << i << endl;
    cout << "The test " << k << " has been finished." << endl;
}

It seems like std::lock_guard is no use in 2nd case, Why?

cpplearner
  • 13,776
  • 2
  • 47
  • 72
rsy56640
  • 299
  • 1
  • 3
  • 13
  • 1
    Slightly OT: I commend your use of braces for initializing `std::lock_guard` because I once wrote a bug as following: `using namespace std; /*...*/ mutex mutex_; /*...*/ lock_guard lock(mutex);` – note the missing underscore and that this is therefore a (useless) function declaration according to the [Most Vexing Parse](https://en.wikipedia.org/wiki/Most_vexing_parse)… This cannot happen when using braces. – Arne Vogel Aug 22 '18 at 12:23
  • The lesson here is more to never use `using namespace std;`.. – Danvil Sep 09 '21 at 03:23

1 Answers1

17

This declaration

std::lock_guard<std::mutex> { mtx };

doesn't bind the created object to a name, it's a temporary variable that exists only for this particular statement. Opposed to that, a variable that has a name and is created on the stack lives until the end of the scope in which it's created.

In this CppCon talk (starting at 31:42), the presenter lists the creation of temporary std::lock_guard instances not bound to a local variable as a common bug in the Facebook code base.

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
lubgr
  • 37,368
  • 3
  • 66
  • 117
  • A bit of nit picking: It's more precise to say "complete statement" than "line of code". Newlines are treated the same as any other whitespace in C(++), but for a few minor exceptions like ending a preprocessor directive (if not escaped) or a `//` comment etc. – Arne Vogel Aug 22 '18 at 12:15
  • To be fair, the bug at Facebook is a bit different: Instead of creating a temporary variable, it is creating a new variable :) – Rakete1111 Aug 23 '18 at 07:28