Java 在 1.8 这个版本里,提供了一种叫 StampedLock 的锁,它的性能就比读写锁还要好。

为什么需要StampedLock

ReadWriteLock 支持两种模式:一种是读锁,一种是写锁,ReadWriteLock 支持两种模式:一种是读锁,一种是写锁。而 StampedLock 支持三种模式,分别是:写锁、悲观读锁和乐观读。

含义类似 含义类似
ReadWriteLock 写锁 读锁
StampedLock 写锁 悲观读锁 乐观读(性能好的关键)

StampedLock 里的写锁和悲观读锁加锁成功之后,都会返回一个 stamp;然后解锁的时候,需要传入这个 stamp
StampedLock 提供的乐观读,是允许一个线程获取写锁的,也就是说不是所有的写操作都被阻塞。

和数据库的乐观锁异曲同工之妙

mysql中为了避免多个线程对于一行数据修改多次,用了version的思想,
stamp其实就是多版本思想体现
多版本思想在处理并发问题很常见 例如innodb中为了解决幻读引入了mvcc,java 中解决cas中的ABA问题都用到了多版本。

StampedLock 使用注意事项

  1. 不支持重入
  2. StampedLock 的悲观读锁、写锁都不支持条件变量
  3. 使用 StampedLock 一定不要调用中断操作,如果需要支持中断功能,一定使用可中断的悲观读锁 readLockInterruptibly() 和写锁 writeLockInterruptibly()

    课后思考

    ```java

private double x, y; final StampedLock sl = new StampedLock(); // 存在问题的方法 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) { x = newX; y = newY; break; } else { sl.unlockRead(stamp); stamp = sl.writeLock(); } } } finally { sl.unlock(stamp); } ```

解答

在锁升级的时候没有释放写锁 解决办法:

  1. 把写锁的ws赋值给stamp
  2. 在finally中sl.unlock(ws) //需要把ws移动到外边。

mysql中执行update是什么锁?

后记

mvcc一直有俩个问题
第一是mvcc为什么是undo log版本链条?
第二是mvcc什么时候合并?在事务提交之后?