此comparison of StampedLock and other locks表明,随着竞争的加剧,StampedLock最快。但是,本文以及其他各种文章都没有列出为什么它更快。似乎使用与其他类型的锁相同的CAS语义?谁能解释为什么随着争用的增加它最快?例如,在下面的代码中,writeLock不仅阻止其他writeLock,还阻止readLock。我现在不关心optimisticReadLocks等。只是普通的writeLock ..什么是优点,以及它比ReentrantLock更快(而且它甚至没有可重入性)。
public static void main(String[]args)throws Exception{
StampedLock lk = new StampedLock();
new Thread(() -> {
long stamp = lk.writeLock();
try {
out.println("locked.. sleeping");
TimeUnit.SECONDS.sleep(5);
lk.unlock(stamp);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
long stamp = lk.writeLock();
try {
out.println("locked.. sleeping");
TimeUnit.SECONDS.sleep(5);
lk.unlock(stamp);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
要清楚,当争用增加时,StampedLock在读取时要快得多。编写器速度稍快一些,但不及读取速度快。我会解释原因。
在大多数情况下,使用读写锁时,写入的方式会更少。但是,尽管如此,每当您在readLock()
上获取ReentrantReadWriteLock
时,都必须增加读取器计数。这会在使用此锁的所有内核上强制缓存无效。
在激烈的争用下,这可能会导致读取时显着降低速度。读取应该很快,当执行readLock()
时,我们不必更新变量,这很直观。
如果相反,我们有图章,或者说是版本,该怎么办?每个读取迭代仅更新一次的程序。
这对我们的作用是,在争用中,如果只有一个线程更新标记值(比如说在写之后),那么当想要在锁上进行读取时,所有读取线程将执行高速缓存命中。这禁止了缓存无效,并允许以比RRWL更合适的方式执行锁定。
[使用StampedLock
的模式类似于使用tryOptimisticRead
时的无锁算法(如CAS)