StampedLock是Java 8新增的一种锁机制,它可以看作是读写锁的加强版,性能比ReadWriteLock更优。StampedLock分为四种模式:写模式、悲观读模式、乐观读模式和试图获取锁的模式。
StampedLock的使用步骤如下:
-
创建一个StampedLock对象
-
使用writeLock获取写锁,使用readLock获取读锁,使用tryOptimisticRead获取乐观读锁
-
如果使用乐观读锁,需要在该锁保护的共享数据上调用validate方法,检查在乐观读锁获取后,该数据是否被其他线程修改过。如果没有被修改,直接使用数据;如果被修改,需要重新获取锁
-
在操作共享数据完毕后,释放锁
下面是一个使用StampedLock的示例代码:
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.StampedLock;
public class StampedLockDemo {
private Map<Integer, String> map = new HashMap<Integer, String>();
private StampedLock lock = new StampedLock();
// 写操作,使用写锁
public void put(int key, String value) {
long stamp = lock.writeLock(); // 获取写锁
try {
map.put(key, value);
} finally {
lock.unlockWrite(stamp); // 释放写锁
}
}
// 读操作,使用悲观读锁
public String get(int key) {
long stamp = lock.readLock(); // 获取悲观读锁
try {
return map.get(key);
} finally {
lock.unlockRead(stamp); // 释放悲观读锁
}
}
// 读操作,使用乐观读锁
public String getOptimistic(int key) {
long stamp = lock.tryOptimisticRead(); // 尝试获取乐观读锁
String value = map.get(key);
if (!lock.validate(stamp)) { // 检查在获取锁后,数据有没有被修改过
stamp = lock.readLock(); // 如果数据被修改过,重新获取悲观读锁
try {
value = map.get(key);
} finally {
lock.unlockRead(stamp); // 释放悲观读锁
}
}
return value;
}
// 试图获取锁的操作
public void putIfAbsent(int key, String value) {
long stamp = lock.tryWriteLock(); // 尝试获取写锁
if (stamp != 0L) { // 如果成功获取锁,执行操作
try {
if (!map.containsKey(key)) {
map.put(key, value);
}
} finally {
lock.unlockWrite(stamp); // 释放写锁
}
} else { // 如果获取锁失败,执行其他操作
// do something else
}
}
}
在上面的示例代码中,我们使用了writeLock和readLock获取写锁和悲观读锁,使用tryOptimisticRead获取乐观读锁,使用tryWriteLock获取试图获取锁的写锁。注意在获取锁之后,需要使用unlockWrite或unlockRead方法释放锁,否则会导致线程一直等待获取锁而无法继续执行。
另外,在使用乐观读锁时,需要注意在validate方法之前,不能有其他线程修改该锁保护的共享数据,否则会导致validate方法返回false,从而触发重新获取悲观读锁的操作。