【悲观锁】Synchronized和ReentrantLock的区别
【线程方法】多线程下 wait、notify、park、unpark 和 await、signal 的区别
【同步工具】CyclicBarrier和CountDownLatch的区别
StampedLock
是Java并发包中引入的一种乐观读锁、悲观写锁的机制,它比传统的ReentrantReadWriteLock
提供了更高的并发性。
主要特点:
-
三种模式:
- 写模式(exclusive mode):类似于独占写锁。
- 读模式(shared mode):类似于共享读锁。
- 乐观读模式:不锁定资源,用于读多写少的场景。
-
乐观读:
使用tryOptimisticRead
获取一个戳(stamp),然后进行读操作,读操作之后可以使用validate
验证戳是否仍然有效。如果有效,操作成功;如果无效,需要使用悲观读锁进行处理。 -
读锁转换为写锁的可能性:
在乐观读的基础上,如果发现数据已经被修改,可以通过调用tryConvertToWriteLock
将乐观读锁转换为悲观写锁。 -
读锁升级为写锁的可能性:
在读锁的基础上,可以通过tryConvertToWriteLock
尝试将读锁升级为写锁。
import java.util.concurrent.locks.StampedLock;
public class StampedLockExample {
private double x, y;
private final StampedLock lock = new StampedLock();
public void write(double newX, double newY) {
long stamp = lock.writeLock();
try {
x = newX;
y = newY;
} finally {
lock.unlockWrite(stamp);
}
}
public double[] optimisticRead() {
long stamp = lock.tryOptimisticRead();
double currentX = x, currentY = y;
if (!lock.validate(stamp)) {
stamp = lock.readLock();
try {
currentX = x;
currentY = y;
} finally {
lock.unlockRead(stamp);
}
}
return new double[]{currentX, currentY};
}
public double[] read() {
long stamp = lock.readLock();
try {
return new double[]{x, y};
} finally {
lock.unlockRead(stamp);
}
}
public void writeWithOptimisticRead(double newX, double newY) {
long stamp = lock.writeLock();
try {
// 乐观读
long optimisticStamp = lock.tryOptimisticRead();
double currentX = x, currentY = y;
if (!lock.validate(optimisticStamp)) {
// 乐观读失败,升级为悲观读
optimisticStamp = lock.readLock();
try {
currentX = x;
currentY = y;
} finally {
lock.unlockRead(optimisticStamp);
}
}
// 执行写操作
x = newX;
y = newY;
} finally {
lock.unlockWrite(stamp);
}
}
public static void main(String[] args) {
StampedLockExample example = new StampedLockExample();
// 写入数据
new Thread(() -> {
example.write(1.0, 2.0);
}).start();
// 悲观读取数据
new Thread(() -> {
double[] result = example.read();
System.out.println("Pessimistic Read data: (" + result[0] + ", " + result[1] + ")");
}).start();
// 乐观读取数据
new Thread(() -> {
double[] result = example.optimisticRead();
System.out.println("Optimistic Read data: (" + result[0] + ", " + result[1] + ")");
}).start();
// 写入数据并使用乐观读
new Thread(() -> {
example.writeWithOptimisticRead(3.0, 4.0);
}).start();
}
}