Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Thread access issue with class member variables

After using threads for a while, I got into a situation where I needed a thread to run forever until a a function (or any sort of event) was called. To do this I created a bool value to control a while loop inside the function that was executed by the thread, but I quickly noticed that external variables are not updated after a thread starts running, causing the thread to never stop when it was asked to.

Heres some simple code to represent the issue:

#include <cstdio>
#include <thread>
#include <chrono>

class A {
public:
    A();

    void startThread();
    void endThread();
private:
    void threadCall();
    bool active;
};

int main() {
    A threadThing;
    threadThing.startThread();
    printf("[M] Thread Created\n");
    std::this_thread::sleep_for(std::chrono::seconds(5));
    threadThing.endThread();
    printf("[M] Thread Killed\n");
    std::this_thread::sleep_for(std::chrono::seconds(5));

    return 0;
}

A::A() {
    active = false;
}

void A::startThread() {
    active = true;
    std::thread AThread(&A::threadCall, *this);
    AThread.detach();
}

void A::endThread() {
    active = false;
}

void A::threadCall() {
    printf("[T] Thread Started\n");
    while (active) {
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }
    printf("[T] Thread Ended\n");
}

The expected result of this would be that the main function starts the thread, the thread says it started, then 4 seconds later the thread is killed and the thread says it ended, when in reality the thread never says it ends. Is there a way to let the thread access the 'active' variable, or is my approach to this problem incorrect altogether? (Side note, I did try to figure this out on my own but only got stuff like local thread storage which seems like its only for storage inside of threads, not access to the outside but I could be wrong)

like image 892
Lemon Drop Avatar asked Dec 25 '13 03:12

Lemon Drop


People also ask

Are class variables thread safe?

Given the structure of the JVM, local variables, method parameters, and return values are inherently "thread-safe." But instance variables and class variables will only be thread-safe if you design your class appropriately.

How do you access member variables in a class?

To access class variables, you use the same dot notation as with instance variables. To retrieve or change the value of the class variable, you can use either the instance or the name of the class on the left side of the dot.

Do threads share class variables?

Yes they are shared, so you have to handle exclusion with some primitives or if you can afford it use "synchronized" methods. Threads don't share anything by themselves, you have to make them share whatever it is fields/properties.

Are private variables thread safe?

On its stack(basically thread stack), local primitives and local reference variables are stored. Hence one thread does not share its local variables with any other thread as these local variables and references are inside the thread's private stack. Hence local variables are always thread-safe.


1 Answers

The problem is with the constructor of std::thread, it copies/moves by default.

std::thread AThread(&A::threadCall, *this);

this copies the object into the new thread, so checking the active variable in the new object has no effect.

you can remove the *

std::thread AThread(&A::threadCall, this);

you pass the object pointer into the new thread, it will call like the method like this(*this).threadCall().

Edit: as the comments say, this is not guarantee to be thread safe, you need to use std::atomic<bool> to be safe.

like image 157
yngccc Avatar answered Oct 21 '22 10:10

yngccc