synchronized 实现原理

1. 可重入锁

概念: 可重入锁(Reentrant Lock)意味着锁是基于线程的,而不是基于调用的。这意味着同一个线程可以多次获取自己已经持有的锁,而不会发生死锁。这种设计能够简化代码的复杂性,尤其是在调用链条中涉及多次锁定的情况下。

Java中的实现:

  • ReentrantLock: 这是 Java 中显式锁的实现类,它可以替代 synchronized,提供更多的功能,比如尝试获取锁、可中断的锁获取、定时获取锁等。
  • synchronized: 隐式可重入锁的实现。

例子: 如果一个线程已经在一个同步方法中获得了某个对象的锁,那么它可以在同一个对象的另一个同步方法中再次获取该锁,而不需要再次进行锁竞争。

2. synchronized 的实现原理

基于 monitor: synchronized 是通过 monitor 对象实现的,每个 Java 对象都有一个 monitor。当一个线程获得了对象的 monitor 时,该对象就被锁定。其他线程若要访问这个对象,就需要等待该 monitor 被释放。

指令:

  • monitorenter: 当线程进入同步代码块时,会尝试获取对象的 monitor。
  • monitorexit: 当线程离开同步代码块时,会释放对象的 monitor。

3. synchronized 的缺点

性能问题:

  • 重量级锁: 在 Java SE 1.6 之前,synchronized 被认为是重量级锁,因为它涉及频繁的上下文切换,这会导致较高的系统资源消耗。
  • 上下文切换: 当线程在获取锁时被阻塞,它会被挂起并等待唤醒,而每次上下文切换都会带来一定的开销。

4. 锁升级机制

Java SE 1.6 引入了锁升级机制,旨在优化不同场景下的锁性能。锁的状态可以在无锁、偏向锁、轻量级锁、重量级锁之间动态转换。

  • 无锁: 初始状态,没有线程访问同步代码块。
  • 偏向锁: 如果只有一个线程访问锁,锁会偏向这个线程,避免不必要的开销。
  • 轻量级锁: 如果有少量的线程竞争,锁会升级为轻量级锁,采用 CAS 操作来实现锁的获取与释放,避免线程阻塞。
  • 重量级锁: 当竞争激烈时,锁会膨胀为重量级锁,此时线程会被阻塞,等待锁的释放。

5. 锁升级的优缺点

  • 偏向锁:
    • 优点: 加锁和解锁操作几乎没有开销,适合单线程场景。
    • 缺点: 如果线程之间存在竞争,锁撤销会产生额外开销。
  • 轻量级锁:
    • 优点: 线程不会阻塞,提高了执行效率,适合响应时间要求高的场景。
    • 缺点: 自旋会消耗 CPU 资源,适合同步代码块执行时间短的场景。
  • 重量级锁:
    • 优点: 不消耗 CPU(因为线程被阻塞),适合同步代码块执行时间长的场景。
    • 缺点: 线程阻塞和唤醒会导致较大的性能开销。

总结

  • 可重入锁和 synchronized 是 Java 多线程编程中的基础概念,理解它们的实现原理和优化机制有助于写出高效的并发代码。
  • 锁升级机制使得 synchronized 在多种并发场景中表现出色,但选择合适的锁类型(例如使用 ReentrantLock)和优化代码结构,仍然是提高并发性能的关键。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员-杨胡广

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值