Most blogsites like this one for example when explaining about memory_order_seq_cst always talks about this example
std::atomic<bool> x{false}, y{false};
std::atomic<int> z{0};
void thread1() {
x.store(true, std::memory_order_seq_cst); // (1)
}
void thread2() {
y.store(true, std::memory_order_seq_cst); // (2)
}
void read_x_then_y() {
while (!x.load(std::memory_order_seq_cst)); // (3)
if (y.load(std::memory_order_seq_cst)) ++z; // (4)
}
void read_y_then_x() {
while (!y.load(std::memory_order_seq_cst)); // (5)
if (x.load(std::memory_order_seq_cst)) ++z; // (6)
}
int main()
{
std::thread a(thread1), b(thread2), c(read_x_then_y), d(read_y_then_x);
a.join(), b.join(), c.join(), d.join();
assert(z.load() != 0); // (7)
}
When translating this into java code i get this
public static void main(String[] args)throws Exception
{
AtomicBoolean
x=new AtomicBoolean(false),
y=new AtomicBoolean(false);
AtomicInteger z=new AtomicInteger(0);
while(true)
{
z.set(0);
Thread t1=new Thread(()->x.set(true));
Thread t2=new Thread(()->y.set(true));
Thread t3=new Thread(()->
{
while(!x.get()){}
if(y.get()){z.incrementAndGet();}
});
Thread t4=new Thread(()->
{
while(!y.get()){}
if(x.get()){z.incrementAndGet();}
});
t1.start();
t2.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
assert(z.get()!=0);
}
}
The whileloop is used to generate infinite test cases to see if the assert fails at any point and the set() from the documentation has similar memory effects to setVolatile() which if we read from the API note has memory effects like memory_order_seq_cst
This example works but i fell is deceptive because it does not explain how memory_order_seq_cst ensures the assertion is always true. The program itself appears to be written in such a way that regardless of what memory_order method you use to load/store
set(),setPlain(),setOpaque(),setRelease()
get(),getPlain(),getOpaque(),getAquire()
the assertion always succeeds and it never fails so how exactly does memory_order_seq play a unique role in this example?