全网最全本科生必用TOP8AI论文写作软件测评
2026/1/16 23:36:16
Java中的synchronized本质上是通过操作系统层面的互斥锁(Mutex Lock)实现的,具体依赖于内核态的系统调用和CPU的硬件原子指令。
Java代码层: synchronized方法/代码块 ↓ JVM层: Monitor(管程) - 包含_owner、_EntryList、_WaitSet等 ↓ 操作系统层: 互斥锁(Mutex) + 条件变量(Condition Variable) ↓ 硬件层: CPU原子指令(如x86的CMPXCHG) + 内存屏障futex(Fast Userspace muTEX)机制实现// futex系统调用longsyscall(SYS_futex,uint32_t*uaddr,intop,uint32_tval,...);CRITICAL_SECTION和Event对象实现pthread_mutex_lock)pthread_mutex_unlock)|--------------------------------------------------------------| | Mark Word (64 bits) | State | |--------------------------------------------------------------| | unused:25 | identity_hashcode:31 | unused:1 | age:4 | biased_lock:0 | 01 | Normal | | thread:54 | epoch:2 | unused:1 | age:4 | biased_lock:1 | 01 | Biased | | ptr_to_lock_record:62 | 00 | Lightweight Locked | | ptr_to_heavyweight_monitor:62 | 10 | Heavyweight Locked | | | 11 | Marked for GC |// 示例代码publicclassSyncExample{privatefinalObjectlock=newObject();publicvoidmethod(){synchronized(lock){// 锁状态变化// 临界区}}}锁升级流程:
无锁 (01) ↓ 线程首次进入 偏向锁 (01) - 仅记录线程ID,避免CAS ↓ 有竞争 轻量级锁 (00) - 通过CAS自旋尝试获取锁 ↓ 自旋失败/长时间竞争 重量级锁 (10) - 调用操作系统互斥锁// 伪代码展示重量级锁的获取过程voidObjectMonitor::enter(){// 1. 尝试快速获取(CAS)if(CAS(&_owner,NULL,Self)==success)return;// 2. 检查是否重入if(_owner==Self){_recursions++;return;}// 3. 自旋尝试if(TrySpin(Self))return;// 4. 进入内核态等待(真正的系统调用)EnterI();// 调用futex_wait或类似机制}| 锁状态 | 实现方式 | 开销 | 适用场景 |
|---|---|---|---|
| 偏向锁 | CAS修改Mark Word | 最小 | 单线程访问 |
| 轻量级锁 | 自旋+CAS | 中等 | 低竞争、短临界区 |
| 重量级锁 | 系统调用+内核阻塞 | 最大 | 高竞争、长临界区 |
在Linux上,最终可能调用:
# 使用strace跟踪系统调用strace-fjavaYourClass2>&1|grep-E"futex|pthread"# 典型输出futex(0x7f8b380008c8, FUTEX_WAIT_PRIVATE,1, NULL)# 线程阻塞futex(0x7f8b380008c8, FUTEX_WAKE_PRIVATE,1)# 线程唤醒synchronized的最终保障是操作系统的互斥锁这就是为什么ReentrantLock在某些场景下性能更好——它提供了更灵活的API和优化策略,但底层同样依赖于类似的系统机制。