0

I have 2 threads created using lambdas, Inside of lambda i am calling a my function where i am manipulating my global variables.

I believe when we don't pass values to functions inside thread with keyword std::ref(), it will passed by value even though function parameters are reference variables. But here in my program I expect x, y, z variables to print only 0, 0, 0 as I have not used std::ref to pass variables but it prints 9, 0, 0 sometime and 0, 0, 0 other time. Am i missing something here?

Please find my code below

I have tried executed below program to test my output

#include <stdio.h>
#include <iostream>
#include <thread>

using namespace std;

int x = 0;
int y = 0;
int z = 0;

void func(int& a, int& b)
{
    for (int i = 0; i < 10000; ++i)
    {
        a += i;
        b += i;
    }

}

int main()
{
    std::thread t1([]() {
        func(x, z);

    });
    std::thread t2([]() {
        func(y, z);
    });

    cout << "x,y,z=" << x << " " << y << " " << z << " " << endl;
    t1.join();
    t2.join();
    getchar();
    return 0;
}
  • what makes you think [`std::ref`](https://en.cppreference.com/w/cpp/utility/functional/ref) is necessary to [pass by reference](https://stackoverflow.com/questions/18147038/passing-object-by-reference-in-c) ? – Sander De Dycker Aug 09 '19 at 09:46
  • 2
    also : you probably want to join the threads *before* you print the results - otherwise the threads probably haven't finished their work yet. – Sander De Dycker Aug 09 '19 at 09:47
  • Don't pass by reference to a thread. Pass by smart pointer instead if you must not make a copy. – Michael Chourdakis Aug 09 '19 at 09:49
  • @SanderDeDycker when i read about std threads, it says through we define thread function parameters as ref, it has to passed through std::ref? Its't that right? – StackUnwind Aug 09 '19 at 10:46
  • @VinayVinay : in some cases, you need `std::ref` (when you want to copy a "reference" eg.), but not in your case. Your lambda's just access globals. Even if they would capture variables, they can just be [captured by reference](https://en.cppreference.com/w/cpp/language/lambda#Lambda_capture). For more, refer to : [C++ Difference between std::ref(T) and T&?](https://stackoverflow.com/questions/33240993/c-difference-between-stdreft-and-t). – Sander De Dycker Aug 09 '19 at 11:18

1 Answers1

1

You have a problem here. Two threads are writing to the same targets without protection (a mutex), so your results are undefined.

When two threads write to the same variable, unless the operation is atomic the result might not be what you expected.

Example:

int x = 0;
function 1: x++;
function 2: x++;

The result might be 1 instead of the expected 2 because the function 2 might read x as 0, before function 1 has modified it.

Also, you don't wait for the threads to finish as the comment says.

Good practises:

  • When modifying variables, use mutual exclusion (mutex)
  • Avoid passing by reference to a thread function, it's too easy to get the referenced variable out of scope before the thread has the chance to access it. You are possibly referencing a stack object that would go out of scope.
Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78