How Does Java’s synchronized Keyword Work Under the Hood?
This article explains the inner workings of Java's synchronized methods and blocks, detailing the JVM method_info structure, relevant access flags, bytecode generation, monitorenter/monitorexit instructions, and the rules that ensure structured locking even during exceptions.
1. synchronized method
synchronized method bytecode reconstruction
Java method structure in JVM:
method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}Key access_flags values
ACC_SYNCHRONIZED = 0x0020 – marks the method as synchronized, causing the JVM to wrap it with a monitor lock.
ACC_PUBLIC = 0x0001 – makes the method publicly accessible.
Example synchronized method
public synchronized void setBalance(double balance) {
this.balance = balance;
}Corresponding bytecode
public synchronized void setBalance(double);
descriptor: (D)V
flags: ACC_PUBLIC, ACC_SYNCHRONIZED
Code:
stack=3, locals=3, args_size=2
0: aload_0
1: dload_1
2: putfield #2 // Field balance:D
5: return
LineNumberTable:
line 20: 0
line 21: 5
LocalVariableTable:
0 6 0 this Lcom/xiaokunliu/concurrency/sync/syncmethod/Account;
0 6 1 balance DEssence of synchronized methods (JVM spec excerpt)
1) Method-level synchronization is performed implicitly, as part of method invocation and return.
2) A synchronized method is distinguished in the run‑time constant pool's method_info structure by the ACC_SYNCHRONIZED flag, which is checked by the method invocation instructions.
3) When invoking a method with ACC_SYNCHRONIZED set, the executing thread enters a monitor, invokes the method, and exits the monitor whether the method completes normally or abruptly.
4) During the time the executing thread owns the monitor, no other thread may enter it. If an exception is thrown and not handled, the monitor is automatically exited before the exception is rethrown.2. synchronized block
synchronized block bytecode reconstruction
Java synchronized block example
public void addTickets1(int number) {
synchronized (controlCinema1) {
System.out.println(Thread.currentThread().getName() + " get controlCinema1 lock, add number is " + number);
this.vacanciesCinema1 += number;
}
}Corresponding bytecode
public void addTickets1(int);
descriptor: (I)V
flags: ACC_PUBLIC
Code:
stack=5, locals=4, args_size=2
0: aload_0
1: getfield #3 // Field controlCinema1:Ljava/lang/Object;
4: dup
5: astore_2
6: monitorenter
...
53: monitorexit
54: goto 62
57: astore_3
58: aload_2
59: monitorexit
60: aload_3
61: athrow
62: return
Exception table:
from to target type
7 54 57 any
57 60 57 any
LineNumberTable:
line 42: 0
line 43: 7
line 44: 41
line 45: 52
line 46: 62
LocalVariableTable:
0 63 0 this Lcom/xiaokunliu/concurrency/sync/syncAttribute/Cinema;
0 63 1 number IBytecode interpretation
monitorenter performs the lock acquisition.
monitorexit at line 53 releases the lock on normal exit.
monitorexit at line 59 followed by athrow ensures the lock is released when an exception occurs.
monitorenter and monitorexit are JVM instructions that implement synchronization.
Working principle of synchronized blocks (JVM spec excerpt)
1) Synchronization of instruction sequences is typically used to encode the synchronized block of the Java programming language.
2) The Java Virtual Machine supplies the monitorenter and monitorexit instructions to support such language constructs.
3) Proper implementation of synchronized blocks requires cooperation from a compiler targeting the Java Virtual Machine.3. Summary of synchronized mechanism
Structured locking
Structured locking means that for each monitor entry during a method call there is a matching monitor exit, guaranteeing that the number of monitorexit executions never exceeds monitorenter executions, even when exceptions occur.
Core takeaways
The JVM implements synchronized via a single monitor structure that handles both method‑level and block‑level synchronization.
Synchronized blocks release the lock automatically on both normal completion and abrupt termination.
Method‑level synchronization is implicit (only the ACC_SYNCHRONIZED flag appears in bytecode), whereas block‑level synchronization is explicit (monitorenter/monitorexit instructions are visible).
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.
Xiaokun's Architecture Exploration Notes
10 years of backend architecture design | AI engineering infrastructure, storage architecture design, and performance optimization | Former senior developer at NetEase, Douyu, Inke, etc.
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.
