Java StampedLock:修订间差异
建立內容為「 TBD Category:Concurrency」的新頁面 |
无编辑摘要 |
||
第1行: | 第1行: | ||
ReadWriteLock可以解决多线程同时读,但只有一个线程能写的问题。 | |||
如果我们深入分析ReadWriteLock,会发现它有个潜在的问题:如果有线程正在读,写线程需要等待读线程释放锁后才能获取写锁,即读的过程中不允许写,这是一种悲观的读锁。 | |||
要进一步提升并发执行效率,Java 8引入了新的读写锁:StampedLock。 | |||
StampedLock和ReadWriteLock相比,改进之处在于:读的过程中也允许获取写锁后写入!这样一来,我们读的数据就可能不一致,所以,需要一点额外的代码来判断读的过程中是否有写入,这种读锁是一种乐观锁。 | |||
<syntaxhighlight lang="java"> | |||
public class Point { | |||
private final StampedLock stampedLock = new StampedLock(); | |||
private double x; | |||
private double y; | |||
public void move(double deltaX, double deltaY) { | |||
long stamp = stampedLock.writeLock(); // 获取写锁 | |||
try { | |||
x += deltaX; | |||
y += deltaY; | |||
} finally { | |||
stampedLock.unlockWrite(stamp); // 释放写锁 | |||
} | |||
} | |||
public double distanceFromOrigin() { | |||
long stamp = stampedLock.tryOptimisticRead(); // 获得一个乐观读锁 | |||
// 注意下面两行代码不是原子操作 | |||
// 假设x,y = (100,200) | |||
double currentX = x; | |||
// 此处已读取到x=100,但x,y可能被写线程修改为(300,400) | |||
double currentY = y; | |||
// 此处已读取到y,如果没有写入,读取是正确的(100,200) | |||
// 如果有写入,读取是错误的(100,400) | |||
if (!stampedLock.validate(stamp)) { // 检查乐观读锁后是否有其他写锁发生 | |||
stamp = stampedLock.readLock(); // 获取一个悲观读锁 | |||
try { | |||
currentX = x; | |||
currentY = y; | |||
} finally { | |||
stampedLock.unlockRead(stamp); // 释放悲观读锁 | |||
} | |||
} | |||
return Math.sqrt(currentX * currentX + currentY * currentY); | |||
} | |||
} | |||
</syntaxhighlight> | |||
* [https://www.liaoxuefeng.com/wiki/1252599548343744/1309138673991714|使用StampedLock] | |||
[[Category:Concurrency]] | [[Category:Concurrency]] |
2021年5月19日 (三) 02:14的版本
ReadWriteLock可以解决多线程同时读,但只有一个线程能写的问题。
如果我们深入分析ReadWriteLock,会发现它有个潜在的问题:如果有线程正在读,写线程需要等待读线程释放锁后才能获取写锁,即读的过程中不允许写,这是一种悲观的读锁。
要进一步提升并发执行效率,Java 8引入了新的读写锁:StampedLock。
StampedLock和ReadWriteLock相比,改进之处在于:读的过程中也允许获取写锁后写入!这样一来,我们读的数据就可能不一致,所以,需要一点额外的代码来判断读的过程中是否有写入,这种读锁是一种乐观锁。
public class Point {
private final StampedLock stampedLock = new StampedLock();
private double x;
private double y;
public void move(double deltaX, double deltaY) {
long stamp = stampedLock.writeLock(); // 获取写锁
try {
x += deltaX;
y += deltaY;
} finally {
stampedLock.unlockWrite(stamp); // 释放写锁
}
}
public double distanceFromOrigin() {
long stamp = stampedLock.tryOptimisticRead(); // 获得一个乐观读锁
// 注意下面两行代码不是原子操作
// 假设x,y = (100,200)
double currentX = x;
// 此处已读取到x=100,但x,y可能被写线程修改为(300,400)
double currentY = y;
// 此处已读取到y,如果没有写入,读取是正确的(100,200)
// 如果有写入,读取是错误的(100,400)
if (!stampedLock.validate(stamp)) { // 检查乐观读锁后是否有其他写锁发生
stamp = stampedLock.readLock(); // 获取一个悲观读锁
try {
currentX = x;
currentY = y;
} finally {
stampedLock.unlockRead(stamp); // 释放悲观读锁
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
}