乐趣区

StampedLock悲观锁乐观锁

StampedLock java1.8 提供的, 性能比 ReadWriteLock 好.

语法

    final StampedLock sl = new StampedLock();
 
    /**
     * 悲观读锁
     * 与 ReadWriteLock 的读锁相似
     * 允许多个线程进行读操作
     * 与写锁互斥
    **/
    // 获取悲观锁
    long stamp = sl.readLock();
    try {//。。。。}finally {sl.unlockRead(stamp);
       }


    /**
     * 写锁
     * 与 ReadWriteLock 的写锁相似
     * 只允许一个线程进行写操作
     * 与读锁互斥
    **/
     // 获取写锁
    long stamp1 = sl.writeLock();
    try{//。。。}finally {
        // 释放写锁
        sl.unlockWrite(stamp1);
    }


    /**
     * 乐观读锁升级为悲观读
     * 锁的严苛程度变强叫做升级,反之叫做降级
    **/
    // 获取乐观锁
     long stamp = sl.tryOptimisticRead();
     // 判断执行读操作期间, 是否存在写操作, 如果存在则 sl.validate 返回 false
    if (!sl.validate(stamp)){
        // 升级为悲观锁
        stamp = sl.readLock();
        try{//。。。}finally {
            // 释放悲观读锁
            sl.unlockRead(stamp);
        }

StampedLock 提供的乐观读,是允许一个线程获取写锁的,也就是说不是所有的写操作都是被阻塞的。

乐观读和乐观锁是不一样的,乐观读这个操作是无锁的,乐观读认为读的时候不会有写的操作。

示例

import java.util.concurrent.locks.StampedLock;

/**
 * 悲观锁乐观锁
 **/
public class Point {
    private int x;
    private int y;
    final StampedLock sl = new StampedLock();

    // 计算到原点的距离
    int distanceFromOrigin() throws  Exception{
        // 乐观锁
        long stamp = sl.tryOptimisticRead();
        // 读入局部变量, 读的过程数据可能被修改
        int curX = x;
        int curY = y;

        // 判断执行读操作期间, 是否存在写操作, 如果存在则 sl.validate 返回 false
        if (!sl.validate(stamp)){
            // 升级为悲观锁
            stamp = sl.readLock();
            try{
                curX = x;
                curY = y;
            }finally {
                // 释放悲观读锁
                sl.unlockRead(stamp);
            }
        }

        return (int)Math.sqrt(curX*curX + curY*curY);
    }
}

特征

  1. StampedLock 支持三种模式: 写锁、悲观读和乐观读。
  2. 允许多 个线程同时获取乐观锁和悲观读锁。
  3. 只允许一个线程获取写锁,写锁和悲观读锁是互斥的。
  4. 使用 StampedLock 一定不要调用中断操作,如果需要支持中断功能,一定使用可中断的悲观读锁 readLockInterruptibly() 和写锁 writeLockInterruptibly()。
  5. StampedLock 里的写锁和悲观读锁加锁成功之后,都会返回一个 stamp;然后解锁的时候,需要传入这个 stamp。
  6. StampedLock 不支持重入(ReadWriteLock 支持)。
  7. StampedLock 的悲观读锁、写锁都不支持条件变量。
  8. StampedLock 支持锁的降级(通过 tryConvertToReadLock() 方法实现)和升级(通过 tryConvertToWriteLock() 方法实现),但是建议你要慎重使用。

数据库中的乐观锁

  1. 在表中添加一个数值型版本号字段 version。
  2. 每次更新表时都将 version 字段加 1。
  3. 修改数据时使用主键和 version 作为修改条件,version 一致则会修改成功。
  4. 如果修改失败,通过主键查询获取最新数据再执行修改。

码字不易如果对你有帮助请给个关注

爱技术爱生活 QQ 群: 894109590

退出移动版