I'm now trying to find my feet in lock-free programming. In particular I am curious about possible reordering for different memory semantics.

Consider the following example. There are two threads (producer and consumer). Release-acquire memory order is used for synchronization.
Qt Code:
  1. #include <QCoreApplication>
  2. #include <QDebug>
  3. #include <QtConcurrent>
  4.  
  5. QAtomicPointer<QString> ptr;
  6. int data;
  7.  
  8. void producer()
  9. {
  10. QString* p = new QString("Hello");
  11. data = 42;
  12. ptr.storeRelease(p);
  13. }
  14.  
  15. void consumer()
  16. {
  17. QString* p2;
  18. //while (!(p2 = ptr.load())) // ?
  19. while (!(p2 = ptr.loadAcquire()))
  20. ;
  21. Q_ASSERT(*p2 == "Hello"); // never fires
  22. Q_ASSERT(data == 42); // never fires
  23. }
  24.  
  25.  
  26. int main(int argc, char *argv[])
  27. {
  28. QCoreApplication a(argc, argv);
  29. QtConcurrent::run(producer);
  30. QtConcurrent::run(consumer);
  31. return a.exec();
  32. }
To copy to clipboard, switch view to plain text mode 

I'm wondering why it is necessary to use release-acquire semantics here? What might happen if we used the relaxed load in consumer?