The happens-before relationship is a key concept in the Java Memory Model that defines the visibility of memory operations across different threads. If one action happens-before another, the results of the first action are visible to the second action. This concept is crucial for writing thread-safe code without using excessive synchronization.
In the example below, we have two threads: one that writes a value to a shared variable, and another that reads that value. The volatile
keyword creates a happens-before relationship between the write and the read, ensuring visibility.
import java.util.concurrent.atomic.AtomicInteger;
public class HappensBeforeExample {
private static AtomicInteger sharedValue = new AtomicInteger(0);
private static volatile boolean flag = false;
public static void main(String[] args) {
Thread writer = new Thread(() -> {
sharedValue.set(42); // Write to shared variable
flag = true; // Set flag to true
});
Thread reader = new Thread(() -> {
if (flag) { // Check flag
System.out.println(sharedValue.get()); // Read from shared variable
}
});
writer.start();
reader.start();
}
}
How do I avoid rehashing overhead with std::set in multithreaded code?
How do I find elements with custom comparators with std::set for embedded targets?
How do I erase elements while iterating with std::set for embedded targets?
How do I provide stable iteration order with std::unordered_map for large datasets?
How do I reserve capacity ahead of time with std::unordered_map for large datasets?
How do I erase elements while iterating with std::unordered_map in multithreaded code?
How do I provide stable iteration order with std::map for embedded targets?
How do I provide stable iteration order with std::map in multithreaded code?
How do I avoid rehashing overhead with std::map in performance-sensitive code?
How do I merge two containers efficiently with std::map for embedded targets?