Java中常用的锁有以下几种:
1. synchronized关键字
synchronized是Java中最基本的锁,它可以用来修饰方法或代码块。synchronized关键字可以保证同一时刻只有一个线程可以执行被修饰的代码块或方法,从而保证线程安全。
应用场景:适用于简单的线程同步场景,例如对共享变量的读写操作。
代码实现:
“`
public class SynchronizedDemo {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
“`
优点:使用简单,易于理解和掌握。
缺点:只能实现互斥锁,不能实现读写锁。
2. ReentrantLock
ReentrantLock是Java中的可重入锁,它可以实现互斥锁和读写锁。ReentrantLock提供了更灵活的锁定方式,例如可以设置公平锁或非公平锁,可以设置超时时间等。
应用场景:适用于复杂的线程同步场景,例如对多个共享变量的读写操作。
代码实现:
“`
public class ReentrantLockDemo {
private ReentrantLock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
}
“`
优点:可以实现互斥锁和读写锁,提供了更灵活的锁定方式。
缺点:使用相对复杂,容易出现死锁等问题。
3. ReadWriteLock
ReadWriteLock是Java中的读写锁,它可以同时支持多个读线程和一个写线程。读写锁可以提高并发性能,由于多个读线程可以同时读取共享变量,而写线程需要独占锁。
应用场景:适用于读多写少的场景,例如缓存系统。
代码实现:
“`
public class ReadWriteLockDemo {
private ReadWriteLock lock = new ReentrantReadWriteLock();
private int count = 0;
public void increment() {
lock.writeLock().lock();
try {
count++;
} finally {
lock.writeLock().unlock();
}
}
public int getCount() {
lock.readLock().lock();
try {
return count;
} finally {
lock.readLock().unlock();
}
}
}
“`
优点:可以提高并发性能,支持多个读线程和一个写线程。
缺点:写线程需要独占锁,可能会导致读线程的等待时间过长。
4. StampedLock
StampedLock是Java中的乐观锁,它可以实现读写锁和乐观锁的功能。StampedLock的乐观锁机制可以减少锁的竞争,提高并发性能。
应用场景:适用于读多写少的场景,例如缓存系统。
代码实现:
“`
public class StampedLockDemo {
private StampedLock lock = new StampedLock();
private int count = 0;
public void increment() {
long stamp = lock.writeLock();
try {
count++;
} finally {
lock.unlockWrite(stamp);
}
}
public int getCount() {
long stamp = lock.tryOptimisticRead();
int c = count;
if (!lock.validate(stamp)) {
stamp = lock.readLock();
try {
c = count;
} finally {
lock.unlockRead(stamp);
}
}
return c;
}
}
“`
优点:可以提高并发性能,支持读写锁和乐观锁。
缺点:使用相对复杂,容易出现死锁等问题。
对比:
| 锁类型 | 适用场景 | 优点 | 缺点 |
| — | — | — | — |
| synchronized | 简单的线程同步场景 | 使用简单,易于理解和掌握 | 只能实现互斥锁,不能实现读写锁 |
| ReentrantLock | 复杂的线程同步场景 | 可以实现互斥锁和读写锁,提供了更灵活的锁定方式 | 使用相对复杂,容易出现死锁等问题 |
| ReadWriteLock | 读多写少的场景 | 可以提高并发性能,支持多个读线程和一个写线程 | 写线程需要独占锁,可能会导致读线程的等待时间过长 |
| StampedLock | 读多写少的场景 | 可以提高并发性能,支持读写锁和乐观锁 | 使用相对复杂,容易出现死锁等问题 |