Search code examples
c++multithreadingsynchronizationglobal

Are global variables actually global in their RAM share behavior?


In a multithreaded application, does each thread have its own copy of a given global variable for performance reasons, or can each thread only read/write into the same version?

If the answer is the former, does a mutex Lock(), followed by Unlock() guarantee copying the data into the global variable?

Language is Cpp. Compiler is the default VS compiler. OS is Windows. Target CPU is modern 5+ core.

Many comments suggest that unless otherwise specified, a global variable has only a single copy throughout the application running instance. Is this code totally safe with zero need for any synchronization or any other data accessing protection mechanism?

(C++ pseudo-code. It isn't best-practice, I am just trying to make sure of certain concepts as part of an inquiry.)

//In MyApplication.cpp
    int Variable1 = 0;
    bool ThreadAFinished = false;

    void ThreadAFunction()
    {
        while (true)
        {
            Variable1++;

            if (Variable1 == 1000)
            {
                break;
            }
        }
        ThreadAFinished = true;
    }
    void ThreadBFunction()
    {
        while (true)
        {
            if (ThreadAFinished)
            {
                if (Variable1 < 1000)
                {
                    printf("ERROR");
                }
                else
                {
                    printf("TEST PASSED");
                }
                break;
            }
        }
    }

Solution

  • ...does each thread has its own 'copy' of the global variable...

    Yes, but No.

    "Yes" because, at a low level, at a level that lies beneath anything that has to do with the C++ language, updates to a variable by different threads can be cached in different memory locations.

    "No" because, "cache" is not part of the explanation of how the C++ language works. It is not part of the language's memory model.

    The way the memory model explains it, there is one and only one copy of any given global variable. But when different threads update global variables with no explicit synchronization, then threads are allowed to disagree on the order in which updates to the different variables happened. That disagreement can allow threads to see inconsistent, sometimes corrupt, views of shared data, but it also allows the system to make the most efficient use of the hardware caches, and get the best performance when threads are accessing their private data.

    does a mutex Lock(), followed by Unlock() guarantee copying the data into the global variable proper?

    Locking and unlocking mutexes is one kind of explicit synchronization that a program can use to ensure that different threads see consistent views of the same shared data structure.

    If you have some shared, global structure, and if every thread locks the same shared, global mutex whenever they access the structure, then the structure is safe. What "safe" means is, Every time thread A locks the mutex, then it will see the data structure in the same exact state that some other thread left it in just before the other thread released the mutex.

    If any thread access the structure without locking the mutex though, even if it's a read-only access, the other thread could see the structure in an inconsistent state because different parts of what it sees could come from different levels of "cache."