Synchronized
和 ReentrantLock
都是 Java 中用于实现线程同步的机制,它们都提供了互斥访问共享资源的能力。下面是它们之间的主要区别:
1. 实现方式:
- Synchronized:
synchronized
是 Java 内置的关键字,用于实现原子性的操作和线程的同步。它隐式地获取和释放锁,不需要手动操作。- 在方法上使用
synchronized
关键字时,锁定的是整个方法体;在代码块中使用时,锁定的是代码块。 synchronized
有可重入性,同一个线程可以重复获得同一把锁。
publicsynchronizedvoidsynchronizedMethod() { // synchronized 代码块// ...}
ReentrantLock:
ReentrantLock
是java.util.concurrent.locks
包下的类,提供了显式地锁定和解锁的机制。- 使用
ReentrantLock
需要手动调用lock()
方法进行加锁,然后在finally
块中调用unlock()
方法进行解锁。 ReentrantLock
同样支持可重入性,同一个线程可以重复获得同一把锁。
importjava.util.concurrent.locks.ReentrantLock; publicclassReentrantLockExample { privatefinalReentrantLocklock=newReentrantLock(); publicvoidlockedMethod() { lock.lock(); try { // 代码块// ... } finally { lock.unlock(); } } }
2. 可中断性:
- Synchronized:
synchronized
不支持中断,即一个线程进入了同步代码块,其他线程需要等待。
- ReentrantLock:
ReentrantLock
提供了可中断的锁,即一个线程在等待锁的过程中,可以被中断,不需要一直等待。
ReentrantLocklock=newReentrantLock(); publicvoidinterruptibleMethod() { try { lock.lockInterruptibly(); // 可中断锁定// 代码块// ... } catch (InterruptedExceptione) { e.printStackTrace(); } finally { lock.unlock(); } }
3. 公平性:
- Synchronized:
synchronized
是非公平锁,即线程获取锁的顺序是不确定的。
- ReentrantLock:
ReentrantLock
支持公平锁和非公平锁,默认情况下是非公平锁,但可以通过构造函数指定为公平锁。
4. 条件变量:
- Synchronized:
synchronized
不支持显式的条件变量,但可以使用Object
的wait()
、notify()
、notifyAll()
方法实现基本的等待和通知机制。
- ReentrantLock:
ReentrantLock
提供了Condition
接口,可以通过newCondition()
方法创建一个与锁相关的条件变量,用于线程之间的通信和协调。
ReentrantLocklock=newReentrantLock(); Conditioncondition=lock.newCondition(); publicvoidconditionMethod() throwsInterruptedException { lock.lock(); try { // 代码块// ...// 等待条件condition.await(); // 唤醒等待的线程condition.signal(); } finally { lock.unlock(); } }
5. 性能:
- Synchronized:
synchronized
是 JVM 实现的关键字,属于底层操作,因此在性能上相对较好。
- ReentrantLock:
ReentrantLock
是基于AbstractQueuedSynchronizer
实现的,相对于synchronized
有更多的操作,因此性能相对较低。但在高并发的情况下,ReentrantLock
的性能可能更好。