static member functions and thread-safety

25,850

Solution 1

No you are not correct.

Objects created in a static function are not shared, and this is also the case for any normal functions.

Objects can be shared though if they are declared static themselves, and it does not depends if the function is static or not.

void myFunc()
{
    static MyObject o;
    o.CallMethod(); // here o is shared by all threads calling myFunc
}

When an object is declared static, it is as if the object was a global variable, but only visible in the scope of the function that it is declared into.

Solution 2

Consider this class

class CData
{
public:
    static void func()
    {
        int a;
        static int b;
    }

    int c;
    static int d;
};

int main()
{
    CData::func();
}

Now variable a is local to each call of func(). If two threads call func() at the same time, they get different versions of a.

b is a static local. The value persists between different calls of func(). If two threads call func() at the same time, they access the same version of b so they might need to do synchronisation.

c is an instance variable; it is attached to a particular instantiation of CData. func() cannot access c, except with a trick I'll show below.

d is a static variable. There is one instance of d shared between all uses of class CData so synchronisation may be necessary. It can be used easily from the static function func().

The trick used to access instance data from a static function is to pass a valid object into the function.

e.g.

class CData
{
public:
    static void func(CData *p)
    {
        int a;
        static int b;

        b = p->c;
    }

    int c;
    static int d;
};

int main()
{
    CData data;
    CData::func(&data);
}

Hope that helps.

Solution 3

No you are not correct. And yes, C++ does very much overuse the word "static".

A static class member variable is of course a global with the class acting as a namespace scope and with some access privilege differences if it is private or protected (can only be accessed by the class).

However a static class member function is just like a regular free-function (not class member) and has its own local variables every time it is called.

The only real difference between a static class member function and a regular free-function, apart from its naming convention, is that it has access to private members of a class (and needs an external "instance" of one).

In addition a static class member function can be called from a template with a variable template parameter, invoking what is commonly called "compile-time polymorphism" and is commonly used in meta-programming.

A static "local" variable in any function is a single-instance, on the other hand, is also a bit like a global and is sensitive to thread-contention issues as two threads calling the function access the same instance.

Solution 4

It does not matter if a function is static or not (class method). Only automatic variables can be seen as local to a function. If you have the address of those data, you may access it.

You can use e.g. thread-local storage to assign your output to a dedicated thread context.

Share:
25,850
Tony The Lion
Author by

Tony The Lion

#disgusted

Updated on July 09, 2022

Comments

  • Tony The Lion
    Tony The Lion almost 2 years

    Objects and variables created in a static member function are not considered 'local' as they would in a member function, so that they can now be shared amongst multiple threads right?

    Whereas if you have a member function which creates some object, this would be local to the thread and therefore it is non-shared.

    Am I correct in saying this?

  • Maxim Egorushkin
    Maxim Egorushkin over 13 years
    There are at least 3 ways to create an object. X x; X* x = new X; X* x = new (mem) X.
  • Stephane Rolland
    Stephane Rolland over 13 years
    @Maxim and they would be shared only this way: static X x; static X* x = new X; What does your comment mean/imply ? it's vague !?
  • Maxim Egorushkin
    Maxim Egorushkin over 13 years
    This: X* x = new (mem) X; can create an object shared between threads or processes. And it can be done from a static member function, which proves your statement "Objects created in a static function are not shared" wrong.
  • Stephane Rolland
    Stephane Rolland over 13 years
    @Maxim, I don't use X* x = new (mem) X; but there could be your same problem with X* x = new X;... however in such cases it wouldnt depend upon the difference between a static function and a non static function, which is IMHO what the novice asker has asked for in this question.
  • Fred Nurk
    Fred Nurk over 13 years
    @Maxim: "Objects created in a static function" is referring to local/automatic objects only. E.g. void f() { int local_var; }. I understand your confusion, but it was readily apparent to me – and, I imagine, the majority – what is meant (though it should be spelled out for teaching, etc.).
  • AnyOneElse
    AnyOneElse over 10 years
    this is by far the best explanation I have seen. Thank you. Helped me a lot!
  • ADJ
    ADJ almost 9 years
    Crisp and clear! Best explanation I came across, to the point, thanks a ton!