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 ?
Thanks in advance!
But to answer your question, any thread can access any global variable currently in scope. There is no notion of passing variables to a thread. It has a single global variable with a getter and setter function, any thread can call either the getter or setter at any time.
can global variables be accessed by two threads? Of course yes, since the several threads of the same process share a common virtual address space.
4 Replies. Hello, Your global variable are not thread safe.
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 "";
}
}
Will there be an app-crash if two threads are reading the same variable?
No. Never. If you're only reading from multiple threads, you're always safe.
will there be an app-crash only if one thread writes to a variable which another thread is currently reading?
Not exactly, but it can lead to a crash, and that's what is happening in your code. It's not "dangerous" in terms of crashing an application to read/write simultaneously from multiple threads. The worst case is that you get garbaged values at some places. That by it's own won't crash your app, but it can definitely lead to that eventually. The problem is when the data you're reading has a meaning other then a primitive value (like an integer for example). For example, if you're reading a memory address (pointer), and then try to access the memory at that address, but the memory is already freed, then you're in trouble - and that's what happens in your code. The characters of the string have moved to a new address, but you're trying to read the old address.
To solve your problem, you should wrap the entire operation inside the lock, and you could use a temporary variable for this:
string test(string value = "")
{
m.lock();
if (value == "")
{
string temp = var;
m.unlock();
return temp;
}
else
{
var = value;
m.unlock();
return "";
}
}
The correct solution is in Paul's answer.
Will there be an app-crash if two threads are reading the same variable?
No you can safely read global variable simultaneously (if you know that no one writes to it at the same time). Read operation doesn't modify the global value so it remains the same and all readers "see" the same value.
Or will there be an app-crash only if one thread writes to a variable which another thread is currently reading?
Generally no, at least not because of the simultaneous read vs. write operation. The crash may be a side effect of it. For example if you update a pointer value and read it at the same time then you try to access the data to which the pointer points. If the read value is invalid, most likely you will crash.
furthermore: is this part
// ... if (value == "") { m.unlock(); return var; } // ...
also thread-save?
No. Your mutex m
protects only the local variable value
which has no need to be protected since it is local. But then you release the mutex and copy (read) the global var
variable while another thread may write to it. To make it thread safe, either use std::lock_guard
and then you won't need manually lock/unlock the mutex. or update the code to this:
m.lock();
if (value == "")
{
string ret_val(var);
m.unlock();
return ret_val;
}
I am not using mutexes for my global variables. Could it be that this "situation" can cause an app-crash
As I wrote earlier, yes, as a side effect your app may crash.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With