java.util.concurrent.locks 包中的接口和实现类
Posted XeonYu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java.util.concurrent.locks 包中的接口和实现类相关的知识,希望对你有一定的参考价值。
上一篇
上一篇博客中,我们使用了一个线程安全的Vector来解决多线程下向集合添加数据造成的数据安全问题,本质上还是用的synchronized关键字来实现的线程同步。
但是synchronized有以下缺陷:
- synchronized 不支持公平性,锁一旦释放,任何线程都能去获得释放的锁,很有可能出现其中一个线程一直获取锁资源,其他线程一直获取不到锁资源。
- 如果一个线程不能获取到 synchronized的锁,那该线程就会一直处于阻塞状态,直到获取锁,且不能中断,这样用起来比较死板
等等
而JUC中给我们提供的锁则可以解决上面的问题,而且使用起来更加灵活。
这里先来说一下synchronized和Lock的区别:
- synchronized 是Java关键字,Lock是java类
- synchronized 是自动的,会自动释放锁。Lock是手动的,需要手动上锁,手动释放锁。
- synchronized 无法判断获取锁的状态。Lock可以判断是否获取到锁
- synchronized 如果一个线程获取到锁,其他线程只能一直等待。Lock可以不用一直等待下去,不会造成死锁,使用起来更加灵活。
- synchronized 是可重入的非公平锁,不可以中断。Lock也是可重入锁,但是可以设置是否是公平锁,且可以被中断。
JUC Locks
JUC中的锁都在locks包中,我们先来看看在 java.util.concurrent.locks 包中都有哪些东西。
可以看到有三个接口分别是
- Lock
- ReadWriteLock
- Condition
以及一些实现类,我们重点关注以下实现类即可:
- ReentrantLock
- ReentrantReadWriteLock
- StampedLock
Lock 接口
看看Lock接口定义了哪些方法
- lock() :如果锁可用,则获取锁,如果锁不可用,线程会被阻塞,直到获取到锁。该方法的特点是即使在获取到锁之前调用中断方法,也不会立即响应中断,而是优先继续走获取锁执行任务的逻辑。然后再抛出异常
- lockInterruptably() :类似与lock(),但是该方法优先响应中断,如果在获取锁之前调interrupt,则立刻抛出InterruptedException异常,不再继续走后面的逻辑
- tryLock() : 可以看做是非阻塞版本的lock(), 尝试立即获取锁,如果获取锁成功则返回true,否则返回false
- tryLock(long time, TimeUnit unit) :跟tryLock类似,tryLock是立即返回值,这个方法是在指定时间段内获取到锁时返回true,否则返回false,多了个超时时间
- unlock() :这个没啥好说的,就是释放锁
- newCondition() :返回一个Condition实例,该实例就是用来实现类似于Object中的wait和notify功能的
再来看看哪些类实现了Lock接口
如上所示,ReentrantLock和一些其他锁的内部类都实现了lock这个接口。
ReadWriteLock 接口
先看看ReadWriteLock 的源码
可以看到,就定义了两个方法,且返回值类型是上面的Lock类型
- readLock() :用来读的锁
- writeLock :用来写的锁
再来看看实现这个接口的类
可以看到,有ReentrantReadWriteLock和 StampedLock
ReadWriteLock 维护了一对锁,分别是读锁和写锁,读锁用于只读操作,写锁用于写操作。
那么问题来了,为啥有了Lock接口,还要在弄个ReadWriteLock呢?
因为,我们所说的数据安全问题,都是在写操作(修改数据)中发生的。读数据并不会修改数据,多个线程读一个数据并不会对数据产生安全问题,也就是说只要没有写操作,读锁可以被多个线程同时持有,这样就能大大提高读的效率了。
例如,贴吧,论坛,新闻类的业务场景,文章或帖子可以被评论或回复,这就是一个写入操作,这类业务场景的写入操作并不会很频繁,而浏览则是一个读取操作,这个操作是非常频繁的。
这种场景就很适合使用ReadWriteLock接口了,可以大大提高程序的执行效率。
Condition
Condition接口就是类似于Object类中的wait和notify,用来实现线程之间的通信。但是,Condition要比Object类中的wait和notify强大的多,可以实现精准唤醒,这个后面示例的时候再细说。
Lock接口中已经默认定义了newCondition()方法,返回的就是Condition类型的实例
Condition接口定义了如下方法
await 类似于 Object中的 wait 方法
signal 类似于 Object的 notify 方法
好了,到这里,我们就把java.util.concurrent.locks包中的接口大致了解了一遍,后面的文章我们来用用给我们提供的实现类。
下一篇:
如果你觉得本文对你有帮助,麻烦动动手指顶一下,可以帮助到更多的开发者,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!
以上是关于java.util.concurrent.locks 包中的接口和实现类的主要内容,如果未能解决你的问题,请参考以下文章