Paze
Paze

Reputation: 199

Modifying variables across thread function calls

i am having a bit of a struggle with a mutli-threaded program i am trying to create. Its a pretty simple application im just creating in order to see how multi-threading works and so on :)

okay so the thing is i have 2 threads and 1 variable, Thread1 is supposed to print the variable they have in common once every second or so(time does not really matter, its just an example) then while Thread1 sleeps for 1 second Thread2 comes in and edits its value to something completely different and the next time Thread1 runs its supposed to print the new value assigned by thread2 allthough this is not happening :/ what is happening is that Thread1 prints the default constructors value even tho it got changed, its kind of hard to explain in words so i have linked the simple example below, i am hoping someone can help me understand this. Btw i know i should be using a mutex or a critical section since im sharing a resources between the two, but since they never run at the same time and its just a simple example i just left it out.

Main.cpp

int _tmain(int argc, _TCHAR* argv[])
{
    Printer printer;

    std::thread thread1(&Printer::SetMessage, printer, printer); //Sets the new value of "New Message"
    std::thread thread2(&Printer::Print, printer, &printer); //Prints the message using printf()

    while(true) {
        Sleep(5000); //i have a beakpoint here just to look at the variables once every 5 sec.
    }

    return 0;
}

Printer.cpp

void Printer::Print(Printer &obj) {
    while(true) {
        printf(obj.Message.c_str());
        Sleep(1000);
    }
}

void Printer::SetMessage(Printer &obj) {
    while(true) {
        Sleep(10000);
        obj.Message = "New Message";
    }
}

Printer::Printer(void){
    this->Message = "YOLO";
}


Printer::~Printer(void){}

so i simply want the value of Message to get updated in all other threads, i mean they are using the same object and changing the value in the same damn object, but why will it not stay changed between threads ??? im so confused :S i have only seen examples that do it in the same class, it got so much more complicated(in my brain) once i used multiple classes.

Upvotes: 0

Views: 67

Answers (2)

didierc
didierc

Reputation: 14730

Btw i know i should be using a mutex or a critical section since im sharing a resources between the two, but since they never run at the same time and its just a simple example i just left it out.

Perhaps the thing you've missed is that even though you put sleep instructions in each method in the hope that each thread would be only active while the other is sleeping, there are no guarantees that the program will execute that way.

The only safe way of blocking a thread while the other is active is to coordinate them using a lock.

You should also pass the data by reference to the threads.

Upvotes: 1

Jonathan Wakely
Jonathan Wakely

Reputation: 171263

You pass printer to the thread constructor, which copies the object, so each thread has a different Printer, not the same object.

In fact, your code shouldn't even compile, but std::thread in Visual Studio has a bug that allows this to happen (and that's ignoring the fact you wrote &printer which would pass a pointer, and Printer::print(Printer& obj) doesn't take a pointer).

To pass a reference to the thread function you need to wrap the object using std::ref which creates a reference_wrapper<Printer> that forwards the argument as a reference to the new thread, instead of making a copy and passing the copy to the new thread:

std::thread thread2(&Printer::Print, std::ref(printer), std::ref(printer));

However, even if you fix that, your code has undefined behaviour, because it is unsafe and invalid for two threads to read/write the same memory location without using mutexes or atomic operations to do the updates safely.

Upvotes: 3

Related Questions