On lzq ways

2019-07-22  本文已影响1人  zhengqiuliu

还记得前两年出去面试的时候,面试官总是会问你使用过哪些锁?哪些场景下使用哪些锁等等问题?

首先Java中最经常使用到的synchronized就是一种互斥锁,根据java内存模型happen-before规则又可以保证线程间的同步。所以说管程是解决并发问题的万能钥匙。

ReentrantLock是互斥的可重入锁。同一个线程可以lock多次,并且支持公平锁和非公平锁。

ReadWriteLock读写锁。主要针对读多写少的场景。允许多个线程同时读共享变量;只允许一个线程写共享变量;如果一个写线程正在执行写操作,此时禁止读线程读共享变量。读写锁的写操作是互斥的,当一个线程在写共享变量的时候,是不允许其他线程执行写操作和读操作。

锁的升级:先获取读锁,并且释放之前,读锁再升级为写锁。但是ReadWriteLock并不支持这种升级,读锁还没有释放,此时获取写锁,会导致写锁永久等待,最终导致相关线程都被阻塞,永远没有机会被唤醒。所以锁的升级时不允许的

但是锁的降级是允许的,写锁还没有释放,获取读锁,然后释放写锁,最后再释放读锁,这种场景ReadWriteLock是支持的。

StampedLock锁支持三种锁模式:写锁,悲观读锁和乐观读

在读多写少的场景,StampedLock的性能比ReadWriteLock锁还要好。

其中写锁和悲观读锁的语义和ReadWriteLock的写锁,读锁的语义非常类似,允许多个线程同时获取悲观锁,但是只允许一个线程获取写锁,写锁和悲观读锁是互斥的。不同的是,StampedLock里的写锁和悲观读锁加锁成功之后,都会返回一个stamp。

StampedLock的性能之所以比ReadWriteLock还要好,其关键是StampedLock支持乐观读的方式。ReadWriteLock支持多个线程同时读,但是当多个线程同时读的时候,所有的写操作会被阻塞;而StampedLock提供的乐观读,是允许一个线程获取写锁的,也就是说乐观读这个操作是无锁的。

上一篇下一篇

猜你喜欢

热点阅读