我正在研究Java代码,我需要在其中实现线程。我正在浏览JAVA 8 API,并开始了解印章。任何人都可以告诉我为什么要在多线程中使用StampedLock?什么是Java中的StampedLock?
在此先感谢。
我正在研究Java代码,我需要在其中实现线程。我正在浏览JAVA 8 API,并开始了解印章。任何人都可以告诉我为什么要在多线程中使用StampedLock?什么是Java中的StampedLock?
在此先感谢。
StampedLock是使用ReadWriteLock(由ReentrantReadWriteLock实现)的替代方案。 StampedLock和的ReentrantReadWriteLock之间的主要区别是:
所以,如果你有,你有竞争的情景(否则你不妨使用或简单的Lock
)和比作者更多的读者,使用StampedLock可以显着提高性能。
但是,您应该在跳到结论之前根据您的特定用例来衡量性能。
Heinz Kabutz写了关于StampedLocks in his newsletter和他也作了a presentation about performance。
为java.util.concurrent.locks.StampedLock的API文档说:
StampedLocks设计用作线程安全组件的开发内部工具。他们的使用依赖于他们所保护的数据,对象和方法的内部属性的知识。它们不是可重入的,因此锁定的机构不应该调用其他可能尝试重新获取锁定的未知方法(尽管您可以将戳记传递给可以使用或转换它的其他方法)。读取锁定模式的使用依赖于相关的代码段是无副作用的。未经验证的乐观阅读部分不能调用未知的方法来容忍潜在的不一致。邮票使用有限的表示,并且不具有密码安全性(即,有效的邮票可能是可猜测的)。在连续运行一年后(不止一年),印花值可能会回收。没有使用或验证时间长于此期限的图章可能无法正确验证。 StampedLocks是可序列化的,但总是反序列化到初始解锁状态,所以它们对远程锁定没有用处。
例如, -
class Point {
private double x, y;
private final StampedLock sl = new StampedLock();
void move(double deltaX, double deltaY) { // an exclusively locked method
long stamp = sl.writeLock();
try {
x += deltaX;
y += deltaY;
} finally {
sl.unlockWrite(stamp);
}
}
double distanceFromOrigin() { // A read-only method
long stamp = sl.tryOptimisticRead();
double currentX = x, currentY = y;
if (!sl.validate(stamp)) {
stamp = sl.readLock();
try {
currentX = x;
currentY = y;
} finally {
sl.unlockRead(stamp);
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
void moveIfAtOrigin(double newX, double newY) { // upgrade
// Could instead start with optimistic, not read mode
long stamp = sl.readLock();
try {
while (x == 0.0 && y == 0.0) {
long ws = sl.tryConvertToWriteLock(stamp);
if (ws != 0L) {
stamp = ws;
x = newX;
y = newY;
break;
}
else {
sl.unlockRead(stamp);
stamp = sl.writeLock();
}
}
} finally {
sl.unlock(stamp);
}
}
}
StampedLock支持读写锁定。与ReadWriteLock相反,StampedLock的锁定方法返回一个由长整型值表示的图章。您可以使用这些印章释放锁或检查锁是否仍然有效。另外加盖的锁支持另一种称为乐观锁的锁模式。
ExecutorService executor = Executors.newFixedThreadPool(2);
Map<String, String> map = new HashMap<>();
StampedLock lock = new StampedLock();
executor.submit(() -> {
long stamp = lock.writeLock();
try {
Thread.sleep(100);
map.put("test", "INDIA");
} catch (Exception e) {
} finally {
lock.unlockWrite(stamp);
}
});
Runnable readTask =() -> {
long stamp = lock.readLock();
try {
System.out.println(map.get("test"));
Thread.sleep(100);
} catch (Exception e) {
} finally {
lock.unlockRead(stamp);
}
};
executor.submit(readTask);
executor.submit(readTask);
获取的读取或经由readLock()或writeLock(写锁定)返回稍后用于内的最后块解锁邮票。请记住,加盖的锁不会实现重入特性。每次锁定调用都会返回一个新的戳记,并在没有锁定的情况下阻止,即使同一个线程已经拥有一个锁定。所以你必须特别注意不要陷入僵局。
executor.submit(() -> {
long stamp = lock.tryOptimisticRead();
try {
System.out.println("Optimistic Lock Valid: " + lock.validate(stamp));
Thread.sleep(100);
System.out.println("Optimistic Lock Valid: " + lock.validate(stamp));
Thread.sleep(1000);
System.out.println("Optimistic Lock Valid: " + lock.validate(stamp));
} catch (Exception e) {
} finally {
lock.unlock(stamp);
}
});
executor.submit(() -> {
long stamp = lock.writeLock();
try {
System.out.println("Write Lock acquired");
Thread.sleep(100);
} catch (Exception e) {
} finally {
lock.unlock(stamp);
System.out.println("Write done");
}
});
乐观的读取锁是通过调用tryOptimisticRead(),它总是返回邮票没有如果锁是实际可用阻止当前线程,不管收购。如果已经有写锁定激活,则返回的标记等于零。您可以随时通过调用lock.validate(stamp)来检查邮票是否有效。
什么是_normal multithreading_? – Keppil 2014-09-29 07:10:27
@ SimY4我刚刚阅读了关于doc中的加盖锁。然后我搜索了一下。但是我没有弄清楚为什么我们应该使用它。使用Stamped锁必须有一些优点,这就是为什么Oracle在java 8中引入它的原因。 – Mohit 2014-09-29 07:16:14
@Keppil我编辑了我的问题。谢谢你纠正我。 – Mohit 2014-09-29 07:17:22