Fundamentals 11 min read

Why Changing int to Integer Lets a Non‑volatile Java Loop Terminate

This article explores a classic Java concurrency puzzle where a non‑volatile flag causes an infinite loop, examines how modifying the loop variable from int to Integer or adding volatile affects termination, and explains the underlying JVM memory‑barrier behavior revealed by DeepSeek.

Su San Talks Tech
Su San Talks Tech
Su San Talks Tech
Why Changing int to Integer Lets a Non‑volatile Java Loop Terminate

Problem Statement

The original code defines a static boolean flag set to false and a static int i initialized to 0. The main thread continuously increments i in a while (!flag) loop while a child thread sleeps 100 ms then sets flag = true and prints a message.

Because flag is not declared volatile, the main thread may never see the update, resulting in a dead loop—a classic interview question.

First Micro‑adjustment

The author marks i as volatile (leaving flag non‑volatile). The program now terminates, but the reason is unclear.

Second Micro‑adjustment

Changing i from the primitive int to the wrapper Integer (without any volatile) also makes the program terminate.

DeepSeek Investigation

Feeding the original code to DeepSeek yields a correct explanation of the dead loop and the need for volatile on flag.

When i is an Integer, each i++ creates a new Integer object and updates the reference. Some JVM implementations (e.g., HotSpot) perform a hidden memory barrier on reference writes, which can inadvertently synchronize other variables, allowing the main thread to observe flag = true and exit the loop.

DeepSeek also explains that the putstatic instruction, which updates a static field, triggers this barrier for object references but not for primitive fields.

JVM‑Level Explanation

According to the Java Memory Model (JMM), ordinary reads and writes only require loading from or flushing to main memory; they do not enforce visibility for non‑volatile variables. However, certain JVM actions—such as object reference assignment, method calls, or memory allocation—may implicitly include a memory barrier, causing the working memory to synchronize with main memory.

HotSpot’s implementation adds such a barrier on putstatic for reference types, which explains why changing i to Integer or marking i as volatile both lead to program termination.

Conclusion

The observed behavior is not guaranteed by the JMM; it depends on JVM-specific optimizations. Adding volatile to flag is the reliable solution, while the other tricks work only on JVMs like HotSpot that introduce hidden memory barriers.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaHotSpotvolatileJMMmemory barrier
Su San Talks Tech
Written by

Su San Talks Tech

Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.