synchronized和Lock的区别是什么?
原创synchronized和Lock的区别是什么?
synchronized和Lock是Java中两种常用的同步机制,用于解决多线程并发问题。尽管它们都可以约为线程保险的目的,但它们之间存在一些显著的区别。
1. 基本概念
synchronized是Java语言的关键字,它是一种内建的同步机制。它可以修饰方法或者代码块,实现对对象或类级别的锁的控制。当一个线程访问一个对象的synchronized方法或代码块时,它会获取到对象的锁,其他线程将无法访问该对象的其他synchronized方法或代码块,直到当前线程释放锁。
Lock是一个接口,位于java.util.concurrent.locks包下,它提供了比synchronized更灵活的锁定操作。要使用Lock,需要创建一个实现Lock接口的实例,如ReentrantLock。通过调用Lock接口的lock()和unlock()方法来实现同步。
2. 锁的获取和释放
synchronized的锁获取和释放是隐式的,当线程进入synchronized修饰的方法或代码块时,会自动获取锁;当线程退出该方法或代码块时,会自动释放锁。
Lock需要显式地调用lock()方法来获取锁,并在完成操作后调用unlock()方法来释放锁。这令Lock在使用上更加灵活,但也更容易出错,考虑到如果忘记释放锁,大概引起死锁。
3. 尝试非阻塞地获取锁
synchronized关键字不拥护尝试非阻塞地获取锁,即如果锁已被其他线程持有,当前线程会一直等待。
Lock提供了tryLock()方法,允许线程尝试非阻塞地获取锁。如果锁可用,当前线程立即获取锁并返回true;否则返回false。这令线程可以按照锁的获取情况执行不同的逻辑。
4. 锁中断
synchronized在获取锁时,如果线程被中断,会抛出InterruptedException异常,但无法响应中断。
Lock提供了lockInterruptibly()方法,允许线程在等待锁的过程中响应中断,即在等待锁的过程中,如果线程被中断,会抛出InterruptedException异常。
5. 公平锁
synchronized的锁是非公平的,即锁的获取顺序不保证与线程的请求顺序一致。
Lock默认是非公平锁,但可以通过构造方法创建公平锁(如new ReentrantLock(true)),公平锁会按照线程的请求顺序来分配锁,但公平锁的性能相对较低。
6. 条件变量
synchronized通过Object类的wait()和notify()方法实现条件变量。
Lock提供了更强盛的条件变量拥护,通过newCondition()方法创建一个Condition实例,可以实现更精细的条件控制,如多个条件队列。
示例代码
以下是使用synchronized和使用Lock的示例代码:
// 使用synchronized
public class SynchronizedExample {
public synchronized void method() {
// 业务逻辑
}
}
// 使用Lock
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
private final Lock lock = new ReentrantLock();
public void method() {
lock.lock();
try {
// 业务逻辑
} finally {
lock.unlock();
}
}
}