【784、Synchronized 和 ReentrantLock 的区别】

139 阅读2分钟

Synchronized 和 ReentrantLock 是 Java 中用于实现线程同步的两种机制,它们在功能和使用方式上有一些区别。

  1. 可重入性(Reentrancy):

    • Synchronized 是 Java 内置的关键字,具有隐式的可重入性。这意味着当一个线程获取到对象的锁后,可以多次重复进入该锁所同步的代码块,而不会被阻塞。在同一个线程中,对于 synchronized 块,如果线程已经获得了锁,那么它可以重复获取该锁而不会造成死锁。
    • ReentrantLock 是 java.util.concurrent 包提供的类,也具有可重入性,但需要显式地进行加锁和释放锁的操作。ReentrantLock 提供了 lock() 和 unlock() 方法,需要手动调用它们来获取和释放锁。
  2. 锁的获取方式:

    • Synchronized 是隐式获取锁的方式,当线程进入 synchronized 块或方法时,会自动获取对象的锁,当线程执行完该块或方法时,会释放锁。
    • ReentrantLock 则是显式获取锁的方式,需要手动调用 lock() 方法获取锁,且在使用完之后必须调用 unlock() 方法释放锁。这种显式的获取和释放锁的方式提供了更大的灵活性,例如可以实现尝试获取锁的操作、可中断的获取锁等。
  3. 等待可中断性:

    • Synchronized 在获取锁时,如果锁已被其他线程占用,当前线程将进入阻塞状态,直到获取到锁。这个过程是不可中断的,即使其他线程中断了当前线程,也无法中断该阻塞状态。
    • ReentrantLock 提供了更多的等待可中断性。在获取锁时,可以使用 lockInterruptibly() 方法,该方法允许线程在等待锁的过程中被中断,从而提供了更好的线程控制能力。
  4. 条件变量支持:

    • ReentrantLock 提供了 Condition 接口的支持,可以通过创建多个 Condition 对象来实现更灵活的线程通信和条件等待机制。通过调用 Condition 的 await() 和 signal() 方法,可以使线程在满足特定条件之前等待或唤醒。