c++multithreadingmutex

C++ understanding multithreading with global variables


I have a C++ program which declares some global variables. After that it splits up into several threads to do several tasks. Those threads read and write some of these global variables.

Will there be an app-crash if two threads are reading the same variable? Or will there be an app-crash only if one thread writes to a variable which another thread is currently reading?

So if the answer to my second question would be yes, would the following code sample solve this problem?

#include <string>
#include <thread>
#include <mutex>
using namespace std;

mutex m;
string var = "foo";

// function to provide read and write access
// "protected" with mutex
string test(string value = "")
{
    m.lock();
    if (value == "")
    {
        m.unlock();
        return var;
    }
    else
    {
        var = value;
        m.unlock();
        return "";
    }
}

void thread1()
{
    // use global variable local
    string localVar = test();
}
void thread2()
{
    // overwrite global variable
    test("bar");
}
void thread3()
{
    // use global variable local
    string localVar = test();
}

int main()
{    
    thread t1(thread1);
    thread t2(thread2);
    thread t3(thread3);

    t1.join();
    t2.join();
    t3.join();

    return 0;
}

furthermore: is this part

// ...
if (value == "")
{
    m.unlock();
    return var;
}
// ...

also thread-save?

And my last question: my program currently uses only one mutex to prevent that two threads (the same function!) are running simultaneously. I am not using mutexes for my global variables. Could it be that this "situation" can cause an app-crash (module: "ntdll.dll") with the exception code 0xc0000005?


Solution

  • Mutiple reads are always thread safe. As soon as one thread is writing to a non-atomic variable var whilst other threads are reading from var you're in danger of a race condition. So you're almost there, but use mutex guards (they're RAII and therefore exception safe and cleaner C++), something like:

    #include <mutex>
    #include <string>
    // ...
    std::mutex m;
    std::string var = "foo";
    // ...
    std::string test(const std::string& value = "")
    {
        std::lock_guard<std::mutex> lock(m);
        if (value == "")
        {
            return var;
        }
        else
        {
            var = value;
            return "";
        }
    }