synchronized的原理以及与ReentrantLock的区别

简介: `synchronized`和`ReentrantLock`均为Java线程同步机制,确保共享资源的单一时刻独占访问。`synchronized`关键字直接嵌入JVM,可通过修饰方法或代码块实现对象锁或监视器锁,具备可重入性,依赖Mark Word进行锁状态管理。`ReentrantLock`则需显式调用`lock()`和`unlock()`,提供更灵活控制,如公平锁、尝试锁及条件变量。两者在语法、灵活性和异常处理上有所差异,但均支持可重入性。性能方面,随JDK优化,`synchronized`在某些场景下甚至优于`ReentrantLock`。选择使用哪个取决于具体需求和上下文。

synchronized关键字和ReentrantLock都是Java中用来实现线程同步的重要机制,它们都允许在一个多线程环境中保护临界区,确保同一时刻只有一个线程能够访问共享资源。下面我们将分别探讨这两种机制的原理及其区别。

synchronized的关键字原理

synchronized关键字可以修饰方法或者同步块,在JVM层面实现了互斥锁的语义。当一个线程试图访问synchronized方法或同步块时,它会尝试获取对应的锁。一旦获取到锁,其他线程就无法再获取此锁,直到第一个线程释放锁为止。

  1. 对象锁

    • synchronized修饰一个实例方法时,锁住的是该对象的实例。
    • synchronized修饰一个静态方法时,锁住的是该类的类对象锁。
  2. 监视器锁

    • 每个Java对象都可以作为锁,称为监视器锁。
    • 当一个线程进入synchronized代码块时,会获取对应的监视器锁;当线程退出时,会释放该锁。
    • 监视器锁具有可重入性,这意味着同一个线程可以多次获取同一个锁。
  3. 实现细节

    • 在JVM层面,synchronized关键字通过操作对象头中的Mark Word来实现。
    • Mark Word中包含对象的哈希码、GC分代年龄、锁标志位等信息。
    • 根据锁的状态(无锁状态、偏向锁、轻量级锁、重量级锁),Mark Word会动态改变其存储的内容以适应不同的场景。

ReentrantLock的原理

ReentrantLock是一个显式的锁,它不是通过编译器自动实现的,而是需要程序员手动地去加锁和解锁。ReentrantLock提供了比synchronized更多的灵活性,比如公平性和非公平性的选择、尝试锁、条件变量等。

  1. 可重入性

    • ReentrantLock同样支持可重入性,即一个已经获取锁的线程可以再次获取该锁而不阻塞。
  2. 公平性

    • ReentrantLock提供了公平锁和非公平锁的选择。公平锁按照线程请求锁的顺序来获取锁,而非公平锁则可能让后来的线程先获取锁。
  3. 尝试锁

    • ReentrantLock允许尝试获取锁而不立即阻塞。如果锁不可用,可以选择等待一定的时间后返回。
  4. 条件变量

    • ReentrantLock通过Condition接口提供了条件变量的支持,这使得线程可以等待某个条件成立后再继续运行。

synchronizedReentrantLock的区别

  1. 语法

    • synchronized不需要手动获取和释放锁,由编译器和JVM自动管理。
    • ReentrantLock需要程序员明确地调用lock()unlock()方法来获取和释放锁。
  2. 灵活性

    • synchronized相对简单且易于使用,但提供的功能较少。
    • ReentrantLock提供了更高级的功能,如公平锁、非公平锁、尝试锁等。
  3. 性能

    • 在某些情况下,ReentrantLock可以提供更好的性能,尤其是在需要使用高级功能时。
    • synchronized在JDK 1.6之后也进行了优化,例如引入了偏向锁和轻量级锁等机制,使得在某些情况下性能甚至优于ReentrantLock
  4. 异常处理

    • 使用synchronized时,如果线程因为异常而退出同步块,锁会自动释放。
    • 使用ReentrantLock时,如果线程因为异常而退出,需要通过try-finally结构来确保锁被释放。
  5. 可见性和原子性

    • synchronized不仅提供了互斥性,还隐式提供了内存可见性和有序性保证。
    • ReentrantLock仅提供互斥性,对于可见性和有序性需要额外的同步机制(如volatilehappens-before规则)。

结论

synchronizedReentrantLock各有优势,选择哪一个取决于具体的使用场景。如果你需要更高级的控制能力,比如公平锁或尝试锁,那么ReentrantLock可能是更好的选择。如果你想要简单快速地实现同步,并且不关心额外的高级特性,那么synchronized就足够了。

相关文章
|
7月前
|
Java 编译器
synchronized原理
synchronized原理
|
7月前
|
Java
【面试问题】Synchronized 和 ReentrantLock 区别?
【1月更文挑战第27天】【面试问题】Synchronized 和 ReentrantLock 区别?
|
5月前
|
安全 Java 开发者
Java多线程:synchronized关键字和ReentrantLock的区别,为什么我们可能需要使用ReentrantLock而不是synchronized?
Java多线程:synchronized关键字和ReentrantLock的区别,为什么我们可能需要使用ReentrantLock而不是synchronized?
64 0
|
7月前
|
安全 Java
ReentrantLock 原理你都知道吗?
通过以上步骤和示例代码,你应该对 ReentrantLock 的工作原理有了清晰的理解。欢迎关注威哥爱编程,一起学习成长。
|
7月前
synchronized与ReentrantLock区别与联系
synchronized与ReentrantLock区别与联系
43 0
|
程序员
ReentrantLock与synchronized的区别
ReentrantLock与synchronized的区别
|
Java API 调度
synchronized 和 ReentrantLock 的实现原理是什么?它们有什么区别
synchronized 和 ReentrantLock 的实现原理是什么?它们有什么区别
89 0
synchronized和reentrantlock之间的区别
synchronized和reentrantlock之间的区别
|
算法 Java
【JUC基础】05. Synchronized和ReentrantLock
前面两篇中分别讲了Synchronized和ReentrantLock。两种方式都能实现同步锁,且也都能解决多线程的并发问题。那么这两个有什么区别呢? 这个也是一个高频的面经题。
114 0
|
存储 设计模式 缓存
synchronized原理剖析
synchronized原理剖析

热门文章

最新文章