在Java中,synchronized
和Lock
都是用于实现线程同步的机制。尽管它们都用于解决并发问题,但它们有不同的特性和使用场景。
synchronized
关键字
synchronized
是Java中的一种内置机制,用于实现线程同步。它可以用于方法或代码块,以确保在同一时间只有一个线程可以执行被同步的代码。
用法示例
-
同步方法:
public synchronized void synchronizedMethod() { // 线程安全的代码 }
-
同步代码块:
public void method() { synchronized (this) { // 线程安全的代码 } }
特点
- 简洁易用:使用简单,直接在方法或代码块上添加
synchronized
关键字。- 内置锁:每个Java对象都有一个隐式的内部锁。
- 自动释放锁:当代码执行完毕或遇到异常时,锁会自动释放。
- 不可中断锁:获取锁的线程不能被中断,除非抛出异常或完成任务。
Lock
接口
Lock
接口是Java 5引入的,并发包(java.util.concurrent.locks
)的一部分,提供了更灵活的锁机制。
非公平锁:十分不公平:可以插队 (默认)
公平锁:十分公平:可以先来后到
常用实现类
ReentrantLock
:一个可重入锁,允许同一个线程多次获取同一把锁。ReadWriteLock
:读写锁,允许多个读线程同时访问,但写线程独占访问。
用法示例
-
ReentrantLock:
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockExample { private final Lock lock = new ReentrantLock(); public void performTask() { lock.lock(); try { // 线程安全的代码 } finally { lock.unlock(); } } }
-
ReadWriteLock:
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteLockExample { private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private final Lock readLock = readWriteLock.readLock(); private final Lock writeLock = readWriteLock.writeLock(); public void readTask() { readLock.lock(); try { // 读操作 } finally { readLock.unlock(); } } public void writeTask() { writeLock.lock(); try { // 写操作 } finally { writeLock.unlock(); } } }
特点
- 可中断锁:可以中断尝试获取锁的线程。
- 尝试锁:提供
tryLock()
方法,允许线程尝试获取锁,如果锁不可用,可以立即返回而不是一直等待。- 超时锁:提供
tryLock(long timeout, TimeUnit unit)
方法,允许线程在指定的时间内尝试获取锁。- 更灵活:支持更复杂的同步需求,如公平锁、读写锁等。
选择指南
- 简单同步:如果只是简单地同步代码块或方法,
synchronized
足够,并且代码更简洁。- 复杂同步需求:如果需要中断锁、尝试锁、超时锁或读写锁等高级功能,
Lock
接口提供了更大的灵活性。- 性能:在高竞争环境下,
ReentrantLock
可能比synchronized
具有更好的性能,因为它提供了更多的优化选项。
区别
- 1、Synchronized 内置的Java关键字, Lock 是一个Java类
- 2、Synchronized 无法判断获取锁的状态,Lock 可以判断是否获取到了锁
- 3、Synchronized 会自动释放锁,lock 必须要手动释放锁!如果不释放锁,死锁
- 4、Synchronized 线程 1(获得锁,阻塞)、线程2(等待,傻傻的等);Lock锁就不一定会等待下 去;
- 5、Synchronized 可重入锁,不可以中断的,非公平;Lock ,可重入锁,可以 判断锁,非公平(可以 自己设置);
- 6、Synchronized 适合锁少量的代码同步问题,Lock 适合锁大量的同步代码!