i'm Qt/C++ programmer. Nowadays I'm working on thread-safety and I've saw tons of discussion on this. Then I've listed safety issues under four title:
- Atomicity while read/write variables between threads
- Compiler optimizations on variables which are shared between threads
- Signal interrupt while read/write variables which are shared between threads
- Confusion of concurrent read/write of variables which are shared between threads
I have understood all of these except second clause. I think it's very complex to understand, because it's not explicit. It depends on compiler behaviour and how can i predict the compiler behaviour, right. For example:
int i=0;
void foo()
{
for (;i<100;i++)
{}
{
According to some resources, on above code, the compiler will move i
from memory to cpu's register until counting finished, then will write it back with its final value. So, what happens if another thread attempted to read value of i
while the above code counting. It just zero until counting finished. Because the real value is still on cpu's register until counting finished. Thus, unexpected status will occur. Let's take much further example:
class MyThread : public QThread
{
Q_OBJECT
void run()
{
mutex.lock();
status=true;
mutex.unlock();
}
private:
QMutex mutex;
bool status;
};
int main()
{
MyThread thread;
thread.start();
return 0;
}
On above code, according to Qt Documentation, the member variables of thread
object owned by main thread, because it's initialized in main()
function, and the codes of run()
function is executed on second thread. And I used mutex
object for serialization of accesses and atomicity, so far so good. But how can I know that, the compiler actually initialized mutex
object into memory before second thread used it on run()
function. Because compiler will never saw actual usage of mutex
object in sequential code flow, so it may not load it into memory. For example on compile time, compiler may will delete some variables which are not used in sequential code flow for gain extra memory, or maybe it will write all the member values into memory after some memory order operations. how can i know that? How can we know whether the compiler optimized variable?