java concurrent 锁_JAVA并发编程:concurrent提供了哪些比synchronized更高效的锁

在java.util.locks包下面提供了三种锁,ReentrantLock、ReentrantReadWriteLock和StampedLock,下面一一讲解这三种锁的特点、实现方式以及应用。

通用方法讲解

这三种锁都实现了lock接口,先解读一下Lock接口的方法及含义:

void lock(); 方法,阻塞方法,直到可以获取到锁;

void lockInterruptibly()方法,阻塞方法,直到可以获取到锁或者被其他线程中断;

boolean tryLock();尝试获取锁,获取不到立刻返回

boolean tryLock(long time, TimeUnit unit) throws InterruptedException;尝试获取锁,直到超时;

void unlock();解锁操作

newCondition()方法;实现等待、通知模式,后面例子中会讲解其应用

ReentrantLock

reentrantLock可以实现synchronized的所有功能,并且扩展了更丰富的功能;

reentrant的中文含义是:可重入的意思,也就是它是可重入锁;支持公平锁和非公平锁两种方式支持获取不到锁,可以被中断支持超时设置

7ec5724521c985307d68bff98c9f03dd.png

reentrantLock 与 syn对比

经典的使用方式如下:

d5a700c4143c7d14e81c607698dabc0b.png

lock的使用方式

加锁之后使用try-finally进行逻辑处理与锁的释放。

lock加锁操作会使得HoldCount计数加1,每一个lock都需要对应一个unlock,即便是在同一个线程中,如果调用了两次lock,需要调用两次unlock才能完全释放锁,否则的话,其

他线程是获取不到锁的。

reentrantLock是基于CAS+AQS框架实现的,具体原理在AQS框架章节会讲到;

{!-- PGC_COLUMN --}ReentrantReadWriteLock

ReentrantReadWriteLock实现了读写锁,所谓的读写锁实际上是一对锁,一个是读锁、另一个是写锁;如果写锁没有加锁的话,读锁可以被多个线程持有;而写锁与写锁、写锁与读锁之间是互斥的,只能有一个线程持有;

上面是英文直译,说白一点就是可以多线程同时读数据,一旦有线程写数据,那就其他线程既不能读,也不能写;

通常需要用到线程安全的Map时,我们一般会用HashTable或ConcurrentHashMap;但其实利用HashMap + 读写锁也可以实现,效率比HashTable好。

590c73f0b6c7b8b60ef3db0d6fb27b2b.png

读写锁

StampedLock

stampedLock是JDK8新增的一个锁,这个锁是不可重入的;重入的话会造成死锁。

这个锁主要利用乐观锁机制来优化读写锁的性能,我们知道,对于ReentrantReadWriteLock,在加了读锁的情况下,会阻塞写操作。

stampedLock可以在加了读锁的情况下不阻塞写操作,也就是其他线程依然可以获取写锁。

可以通过validate方法校验加乐观锁之后,数据有没有被修改;

具体用法如下:

8ac2ee255a7d8907eb4245406bd4c974.png

乐观锁

第151行加乐观读锁,第152行读数据;第153行校验加乐观读锁到读取数据完成期间,数据有没有被改变,如果被改变的话,则使用悲观读锁再次进行读,如果没有被改变,则直接返回结果。

感谢您的阅读,如有疑问,欢迎留言评论; 如果觉得读完有所收获,请收藏点赞转发~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值