Java 中的锁 StampedLock
Java juc 锁 About 6,633 words主要方法
readLock()
:获取悲观读锁,阻塞等待。unlockRead()
:释放读锁。writeLock()
:获取悲观写锁,阻塞等待。unlockWrite()
:释放写锁。tryReadLock()
:尝试获取悲观读锁,获取不到就直接返回。tryOptimisticRead()
:尝试获取乐观读标记(不是锁,只是一个标记),获取不到就直接返回。validate()
:验证stamp
标记,返回true
表示锁没有被悲观锁获取,false
反之。
乐观读
tryOptimisticRead()
获得一个stamp
标记,如果stamp
标记为0
,表示被悲观锁锁定了,通过validate()
方法判断当前获取的乐观锁是否生效。
示例代码
public class StampedLockDemo {
public static int x;
public static int y;
public static void main(String[] args) {
StampedLock stampedLock = new StampedLock();
new Thread(() -> {
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(LocalDateTime.now() + " Read Thread id#" + Thread.currentThread().getId() + ", begin to get read lock");
long stamp = stampedLock.readLock();
System.out.println(LocalDateTime.now() + " Read Thread id#" + Thread.currentThread().getId() + ", get read lock success, stamp=" + stamp);
try {
System.out.println(LocalDateTime.now() + " Read Thread id#" + Thread.currentThread().getId() + ", x=" + x + ", y=" + y);
} finally {
stampedLock.unlockRead(stamp);
}
}).start();
new Thread(() -> {
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(LocalDateTime.now() + " Write Thread id#" + Thread.currentThread().getId() + ", begin to get write lock");
long stamp = stampedLock.writeLock();
System.out.println(LocalDateTime.now() + " Write Thread id#" + Thread.currentThread().getId() + ", get write lock success, stamp=" + stamp);
try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); }
try {
x = 10;
y = 10;
System.out.println(LocalDateTime.now() + " Write Thread id#" + Thread.currentThread().getId() + ", x=" + x + ", y=" + y);
} finally {
stampedLock.unlockWrite(stamp);
}
}).start();
new Thread(() -> {
System.out.println(LocalDateTime.now() + " OptimisticRead Thread id#" + Thread.currentThread().getId() + ", begin to get OptimisticRead");
// 获得一个乐观读的标记(不是锁)
long stamp = stampedLock.tryOptimisticRead();
int curX = x;
int curY = y;
// 检查乐观读标记是否被其他写锁更改
if (!stampedLock.validate(stamp)) {
System.out.println(LocalDateTime.now() + " OptimisticRead Thread id#" + Thread.currentThread().getId() + ", get OptimisticRead failed, stamp=" + stamp);
// 获取一个悲观读锁
stamp = stampedLock.readLock();
try {
curX = x;
curY = y;
System.out.println(LocalDateTime.now() + " OptimisticRead transfer to read lock Thread id#" + Thread.currentThread().getId() + ", curX=" + curX + ", curY=" + curY);
} finally {
stampedLock.unlockRead(stamp);
}
} else {
System.out.println(LocalDateTime.now() + " OptimisticRead Thread id#" + Thread.currentThread().getId() + ", get OptimisticRead success, stamp=" + stamp + ", curX=" + curX + ", curY=" + curY);
}
}).start();
new Thread(() -> {
try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(LocalDateTime.now() + " Try Read Thread id#" + Thread.currentThread().getId() + ", begin to get try read lock");
long stamp = stampedLock.tryReadLock();
if (stampedLock.validate(stamp)) {
System.out.println(LocalDateTime.now() + " Try Read Thread id#" + Thread.currentThread().getId() + ", get try read lock success, stamp=" + stamp);
try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
try {
System.out.println(LocalDateTime.now() + " Try Read Thread id#" + Thread.currentThread().getId() + ", x=" + x + ", y=" + y);
} finally {
stampedLock.unlockRead(stamp);
}
} else {
System.out.println(LocalDateTime.now() + " Try Read Thread id#" + Thread.currentThread().getId() + ", get try read lock failed, stamp=" + stamp);
}
}).start();
}
}
输出:
2021-03-18T13:03:00.888 OptimisticRead Thread id#14, begin to get OptimisticRead
2021-03-18T13:03:00.889 OptimisticRead Thread id#14, get OptimisticRead success, stamp=256, curX=0, curY=0
2021-03-18T13:03:01.867 Write Thread id#13, begin to get write lock
2021-03-18T13:03:01.867 Read Thread id#12, begin to get read lock
2021-03-18T13:03:01.867 Write Thread id#13, get write lock success, stamp=384
2021-03-18T13:03:02.867 Try Read Thread id#15, begin to get try read lock
2021-03-18T13:03:02.867 Try Read Thread id#15, get try read lock failed, stamp=0
2021-03-18T13:03:11.867 Write Thread id#13, x=10, y=10
2021-03-18T13:03:11.867 Read Thread id#12, get read lock success, stamp=513
2021-03-18T13:03:11.867 Read Thread id#12, x=10, y=10
不可重入
如果再加一个线程,获取第一把悲观读锁后,再第一把锁未释放时,再获取第二把悲观读锁,导致所有线程阻塞。
new Thread(() -> {
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
long stamp = stampedLock.readLock();
try {
System.out.println("readLock是否可重入?");
try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
long stamp2 = stampedLock.readLock();
try {
System.out.println("readLock可重入!");
try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
} finally {
stampedLock.unlockRead(stamp2);
}
} finally {
stampedLock.unlockRead(stamp);
}
}).start();
程序将无法执行下去,一直停在此处,输出如下:
2021-03-18T13:18:17.644 OptimisticRead Thread id#14, begin to get OptimisticRead
2021-03-18T13:18:17.644 OptimisticRead Thread id#14, get OptimisticRead success, stamp=256, curX=0, curY=0
readLock是否可重入?
2021-03-18T13:18:18.623 Write Thread id#13, begin to get write lock
2021-03-18T13:18:18.623 Read Thread id#12, begin to get read lock
2021-03-18T13:18:19.624 Try Read Thread id#15, begin to get try read lock
2021-03-18T13:18:19.624 Try Read Thread id#15, get try read lock success, stamp=258
2021-03-18T13:18:24.626 Try Read Thread id#15, x=0, y=0
原理
Views: 3,086 · Posted: 2021-04-09
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓
Loading...