java面试题-synchronized和ReentrantLock区别是什么?
在Java多线程编程中,保障线程安全是一个重要的问题。synchronized
和 ReentrantLock
是两种常用的锁机制,用于解决多线程环境下的竞争问题。本教程将详细比较这两者的区别,并提供相应的代码示例,使初学者能够深入理解它们的使用方式和特性。
1. synchronized 和 ReentrantLock 的基本区别
1.1 等待锁的方式
synchronized: 当线程竞争锁失败时,会一直等待,直到获取到锁。
ReentrantLock: 可以尝试获取锁,并得到获取结果,可以通过
tryLock
方法设置等待时间。
1.2 超时设置
synchronized: 无法设置获取锁的超时时间。
ReentrantLock: 可以设置获取锁的超时时间,避免长时间等待。
1.3 公平性
synchronized: 无法实现公平锁,即不能保证等待时间最长的线程最先获取到锁。
ReentrantLock: 可以满足公平锁,即先等待的线程先获取到锁。
1.4 控制等待和唤醒
synchronized: 需要结合加锁对象的
wait()
和notify()
、notifyAll()
方法来控制等待和唤醒。ReentrantLock: 需要结合
Condition
的await()
和signal()
、signalAll()
方法来控制等待和唤醒。
1.5 实现方式
synchronized: 是JVM层面实现的,是一种隐式锁。
ReentrantLock: 是JDK代码层面实现的,是一种显式锁。
1.6 锁的释放
synchronized: 在加锁代码块执行完或者出现异常时,自动释放锁。
ReentrantLock: 不会自动释放锁,需要在
finally{}
代码块中显式释放。
2. 示例代码演示
2.1 synchronized 示例
public class SynchronizedExample {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
public static void main(String[] args) {
SynchronizedExample example = new SynchronizedExample();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Count: " + example.getCount());
}
}
2.2 ReentrantLock 示例
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private int count = 0;
private final Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
return count;
}
public static void main(String[] args) {
ReentrantLockExample example = new ReentrantLockExample();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Count: " + example.getCount());
}
}
3. 代码解释
SynchronizedExample
使用synchronized
关键字来保证线程安全。ReentrantLockExample
使用ReentrantLock
来保证线程安全,并在increment
方法中显式地加锁和解锁。
4. 总结
通过本教程,我们深入了解了 synchronized
和 ReentrantLock
的区别和使用方法。在实际开发中,选择合适的锁机制取决于具体的需求,同时要注意锁的释放,以防止死锁等问题的发生。
- 本文标签: Java 面试题
- 本文链接: https://www.jietongc.com/article/88
- 版权声明: 本文由大熊科技原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权