How JVM Optimizes Locks: Spin Locks, Elimination, and Escape Analysis Explained
This article explains how the JVM improves lock performance through techniques such as spin locks, adaptive spinning, lock elimination, lock coarsening, and escape analysis, illustrating each optimization with code examples, JVM flags, and visual diagrams.
Lock Optimization
During locking, the JVM employs several optimizations—spin locks, adaptive spinning, lock elimination, and lock coarsening—to improve execution efficiency.
1.1 Spin Locks and Adaptive Spinning
On multi‑core processors, a waiting thread can keep the CPU busy by looping for a short timeout instead of yielding, which is known as a spin lock . The JVM enables spin locks by default after JDK 1.6 via the +XX:UseSpinning flag. The number of spin attempts can be tuned with -XX:PreBlockSping (default is 10).
1.2 Lock Elimination
Lock elimination is an optimization where the JIT compiler removes synchronization when it proves that the locked code cannot be accessed by other threads, typically based on escape analysis. If all data used inside a synchronized block are confined to the stack, the lock can be safely omitted.
Example: concatenating three strings does not require synchronization because the strings are immutable and the JIT can replace the operation with a StringBuilder sequence.
public String concatStr(String x, String y, String z) {
return x + y + z;
}After compilation, the code becomes:
public String concatStr(String x, String y, String z) {
StringBuilder sb = new StringBuilder();
sb.append(x);
sb.append(y);
sb.append(z);
return sb.toString();
}Even though StringBuilder is not thread‑safe, the optimizer confines its use to the method scope, so no synchronization is needed.
1.3 Lock Coarsening
Best practice recommends keeping synchronized blocks as small as possible. However, when a series of consecutive operations repeatedly lock and unlock the same object—especially inside loops—the JVM may merge them into a single, larger lock region, reducing the overhead of repeated lock acquisition.
StringBuffer buffer = new StringBuffer();
/** lock coarsening */
public void append(){
buffer.append("aaa").append(" bbb").append(" ccc");
}In this example, the JVM can coarsen the multiple lock/unlock calls into one broader lock covering the entire method.
2 Escape Analysis
Escape analysis determines whether an object’s reference escapes the method or thread that created it. If the object does not escape, the JVM can apply several optimizations:
Stack allocation: allocate objects on the stack, eliminating heap allocation and reducing GC pressure.
Scalar replacement: store object fields directly in CPU registers instead of memory.
Synchronization elimination: omit locks for objects that are guaranteed to be accessed by a single thread.
2.1 Method Escape
An object escapes a method when it is passed to another method or stored in a field that may be accessed elsewhere.
2.2 Thread Escape
An object escapes a thread when it becomes reachable by other threads, for example by being assigned to a shared field.
References
https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
https://www.cnblogs.com/xidongyu/p/10891303.html
https://www.cnblogs.com/kkkkkk/p/5543799.html
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
