Home > Software engineering >  Can object’s property be used, if object used in another thread?
Can object’s property be used, if object used in another thread?

Time:08-10

Can the example below make undefined behavior and crash when main thread try to call SetX, because, although x property is not being accessed in new thread, but object itself is?

class Object{
public:
int x;
int y;

Object(int x, int y)
{
this->x = x;
this->y = y;
}

void SetX(int x)
{
this->x = x;
}

}*object = nullptr;

int *value_only = nullptr;

void ch()
{
    while(true) // assume there is some mechanism to quit loop
    {
         //with obj variable
         //readonly
         auto link = obj;
         auto y = obj->y;

         //write
         obj->y = 5;


         //without obj variable
         //read
         auto yy = *value_only;

         //write
         *value_only = 2;


         // note that obj->x is not touched
    }
}

int main()
{
obj = new Object(1,2);
value_only = &obj->y;

thread th(ch);

obj->SetX(4);

// assume, th termination is handled

return 0;
}

CodePudding user response:

No there is no issue with accessing two different members of the same object.

Note that both members are public and the setter doesn't do anything but set the member. Hence, you could rewrite ch to take a reference to obj->y as parameter and also in main, rather than calling SetX it could use int& x = obj->x;. Maybe then it is more obvious that the two threads do not actually share data.

In the thread you copy obj but that merely copies the pointer.

However, your program will crash due to not joining the thread. std::thread calls std::terminate when not joined (or detached) in its destructor. In any case you leak the memory of obj. While leaking memory on return from main is not a big deal, obj may manage other resources (files, db connections, etc) that need to be properly closed in the destructor.

CodePudding user response:

My comments in code :

#include <future>
#include <mutex>

class Object
{
public:
    Object(int x, int y) :
        m_x{ x },
        m_y{ y }
    {
    }

    void SetX(int x)
    {
        m_x = x;
    }

    int GetX()
    {
        return m_x;
    }

private:
    int m_x;        
    int m_y;
};

int main()
{
    auto obj_ptr = std::make_shared<Object>(1, 2);

    // capture obj_ptr by value, making a copy of shared_ptr will increase its 
    // reference count. When the lambda finishes the shared_ptr will decrease the reference count.
    auto future = std::async([obj_ptr]
        {
            obj_ptr->SetX(3);
        });

    // destructor of the future will block until async is complete
    // so no race condition at shutdown
    return 0;
}
  • Related