时间:2022-07-02 10:31:30 | 栏目:JAVA代码 | 点击:次
StampedLock:
StampedLock是并发包里面JDK8版本新增的一个锁,该锁提供了三种模式的读写控制,当调用获取锁的系列函数时,会返回一个long 型的变量,我们称之为戳记(stamp),这个戳记代表了锁的状态。其中try 系列获取锁的函数,当获取锁失败后会返回为0的stamp值。当调用释放锁和转换锁的方法时需要传入获取锁时返回的stamp值。
StampedLock提供的三种读写模式的锁分别如下:
StampedLock还支持这三种锁一定条件下进行相互转换。例如long tryConvertToWriteLock(long stamp)期望把stamp 标示的锁升级为写锁,
这个函数会在下面几种情况下返回一个有效的stamp(也就是晋升写锁成功):
另外,StampedLock 的读写锁都是不可重入锁,所以在获取锁后释放锁前不应该再调用会获取锁的操作,以避免造成调用线程被阻塞。当多个线程同时尝试获取读锁和写锁时,谁先获取锁没有一定的规则,完全都是尽力而为,是随机的。并且该锁不是直接实现 Lock 或 ReadWriteLock 接口,而是其在内部自己维护了一个双向阻塞队列。
下面通姑JDK8里面提供的一个管理二维点的例子来理解以上介绍的概念。
package LockSupportTest;
import com.sun.org.apache.bcel.internal.generic.BREAKPOINT;
import java.util.concurrent.locks.StampedLock;
public class Point_Class {
private double x,y;
private final StampedLock sl = new StampedLock();
void move(double deltaX, double deltaY) {
long stamp = sl.writeLock();
try {
x += deltaX;
y += deltaY;
} finally {
sl.unlockWrite(stamp);
}
}
double distanceFromOrin() {
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) {
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);
}
}
}
在如上代码中,Point类里面有两个成员变量(x,y)用来表示一个点的二维坐标,和三个操作坐标变量的方法。另外实例化了一个StampedLock对象用来保证操作的原子性。