目录
Synchronized 与 ReentrantLock 的区别
在 Java 多线程编程中,Synchronized 和 ReentrantLock 都是实现线程同步的机制,它们之间既有相似之处,也存在一些区别。
一、相似之处
- 同步机制:二者都是为了保证线程安全,确保在同一时刻只有一个线程能执行被同步的代码块。
- 可重入性:一个线程可以多次获取同一把锁而不会发生死锁。
- 互斥锁本质:本质上都是互斥锁。
二、区别
- 灵活性
- Synchronized:是 Java 语言内置的关键字,使用非常简单,但功能相对有限。可以放在方法前面修饰,也可以用于同步代码块。
- ReentrantLock:是一个类,提供了更高级的锁功能。例如,可以中断锁的获取、超时获取锁、非阻塞尝试获取锁等,还能实现更复杂的同步结构。
- 性能
- 低竞争情况:在锁竞争比较低的情况下,JDK 内部对 Synchronized 做了很多优化,如锁消除、锁粗化等,此时它的性能非常不错,甚至比 ReentrantLock 性能还要高。
- 高竞争情况:在高竞争环境下,ReentrantLock 的性能可能会更好,并且它可以提供非公平、公平锁模式,不同业务场景下选择不同的锁模式,性能可能会不一样。
- 实现功能角度
- Synchronized:一般在代码块结束时自动释放锁,与方法块、代码块强绑定。
- ReentrantLock:通过
lock和unlock方法控制锁的获取和释放,可以在任何位置灵活调用。还提供了tryLock、interruptedNear方法,可以及时响应中断和超时。
- 条件变量
- ReentrantLock:具有与之关联的
Condition条件变量对象,可以搭配lock来更细腻地控制线程的通信。 - Synchronized:一般配合对象的
wait、notify或notifyAll方法来进行线程之间的通信,但这种方式不如Condition对象灵活。
- ReentrantLock:具有与之关联的
三、使用场景
- Synchronized:适用于简单的同步场景,小规模、多线程竞争不高的情况下性能较好。适合开发者在不太想处理复杂生命周期的时候使用,使用起来很方便。
- ReentrantLock:适用于高级的同步控制场景,特别是系统规模比较大、线程数比较多、竞争比较大的复杂同步需求场景。例如需要公平锁、可中断锁、带超时功能的锁等情况。
以下是一个使用ReentrantLock的示例代码:
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private final ReentrantLock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
return count;
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockExample example = new ReentrantLockExample();
Thread t1 = new Thread(example::increment);
Thread t2 = new Thread(example::increment);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Count: " + example.getCount());
}
}
总之,在选择使用 Synchronized 还是 ReentrantLock 时,需要根据具体的业务场景和需求来决定。如果是简单的同步场景,可以优先考虑使用 Synchronized;如果需要更高级的同步控制功能,则可以选择 ReentrantLock。
255

被折叠的 条评论
为什么被折叠?



