高性能的StampedLock锁

StampedLock 支持的三种锁模式:

1.ReadWriteLock 支持两种模式:一种是读锁,一种是写锁

2.StampedLock 支持三种模式,分别是:写锁、悲观读锁和乐观读
    1)写锁、悲观读锁的语义和 ReadWriteLock 的写锁、读锁的语义非常类似,
    2)允许多个线程同时获取悲观读锁,但是只允许一个线程获取写锁,写锁和悲观读锁是互斥的
    3)不同的是:StampedLock 里的写锁和悲观读锁加锁成功之后,都会返回一个 stamp;然后解锁的时候,需要传入这个 stamp
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.StampedLock;

class Point {
    public static void main(String[] args) throws InterruptedException {
        final StampedLock lock = new StampedLock();
        Thread T1 = new Thread(()->{
            // 获取写锁
            lock.writeLock();
            // 永远阻塞在此处,不释放写锁
            LockSupport.park();
        });
        T1.start();
        // 保证T1获取写锁
        Thread.sleep(100);
        Thread T2 = new Thread(()->
                //阻塞在悲观读锁
                lock.readLock()
        );
        T2.start();
        // 保证T2阻塞在读锁
        Thread.sleep(100);
        //中断线程T2
        //会导致线程T2所在CPU飙升
        T2.interrupt();
        T2.join();
    }
}

分析:

1.线程 T1 获取写锁之后将自己阻塞,线程 T2 尝试获取悲观读锁,也会阻塞;

2.此时调用线程 T2 的 interrupt() 方法来中断线程 T2 的话,你会发现线程 T2 所在 CPU 会飙升到 100%3.所以,使用 StampedLock 一定不要调用中断操作,
    如果需要支持中断功能,一定使用可中断的悲观读锁 readLockInterruptibly() 和写锁 writeLockInterruptibly()

 

使用 StampedLock的最佳实践demo:

StampedLock 读模板:

import java.util.concurrent.locks.StampedLock;

class Point {
    public static void main(String[] args) throws InterruptedException {
        final StampedLock sl = new StampedLock();

        // 乐观读
        long stamp = sl.tryOptimisticRead();
        // 读入方法局部变量
        ......
        // 校验stamp
        if (!sl.validate(stamp)){
            // 升级为悲观读锁
            stamp = sl.readLock();
            try {
                // 读入方法局部变量
                .....
            } finally {
                //释放悲观读锁
                sl.unlockRead(stamp);
            }
        }
        //使用方法局部变量执行业务操作
        ......
    }
}

 

StampedLock 写模板:

import java.util.concurrent.locks.StampedLock;

class Point {
    public static void main(String[] args) throws InterruptedException {
        final StampedLock sl = new StampedLock();
        long stamp = sl.writeLock();
        try {
            // 写共享变量
            ......
        } finally {
            sl.unlockWrite(stamp);
        }
    }
}

 

posted @ 2020-11-07 16:14  天天大傻猫  Views(106)  Comments(0Edit  收藏  举报