并发编程实战学习笔记(九)-显式锁

为什么创建一种与内置锁如此相似的新加锁规则(显示锁)?

内置锁的局限

  • 无法中断一个正在等待锁的线程,或者获取锁时不支持超时操作。
  • 内置锁必须在获取锁的代码块中释放,这就简化了编码工作,并且与异常处理操作实现了很好的互动,但却无法实现非阻塞结构的加锁规则。

显示锁的优势

  • 轮询锁与定时锁。

可定时的与可轮询的锁获取模式是由tryLock方法实现的,与无条件的锁获取模式相比,它具有更完善的错误恢复机制。在内置锁中,死锁是一个严重的问题,恢复程序的唯一办法是重新启动程序,而防止死锁的唯一方法就是在构造程序时避免出现不一致的锁顺序。可定时的与可轮询的的锁提供了另一种选择,避免死锁的发生。通过重新获取及释放锁来避免死锁。

  • 可中断的锁获取操作。
  • 非块结构的加锁。
  • 性能考虑因素。经过优化,目前内置锁的性能与显示锁的性能已经差不了多少了,所以这点一般可以忽略,除非你要利用显示锁实现更加复杂的优化手段。

公平性对性能影响

大多数情况下,非公平锁的性能要高于公平锁的性能,原因是后者为了实现公平,会有更多的线程上下文切换成本。

当持有锁的时间较长,或者请求锁的平均时间间隔较长,那么应该使用公平锁。在这些情况下,允许“插队”带来的吞吐量提升(当锁处于可用的状态时,线程却还处于被唤醒的过程中)则可能不会出现。

在synchronized和ReentrantLock之间的选择

在一些内置锁无法满足需求的情况下,ReentrantLock可以作为一种高级工具。当需要一些高级功能时才应该使用ReentrantLock,这些功能包括:可定时的、可轮询的与可中断的锁获取操作,公平队列,以及非块结构的锁。

否则,还是应该优先使用synchronized.

读写锁

内在实现机制

  • ReentrantReadWriteLock在读写锁都提供了可重入的加锁语义。
  • 在构造时也可以指定是一个非公平的锁(默认)还是一个公平的锁。在公平的锁中,等待时间最长的的线程将优先获得锁。
  • 读写锁之间的协调关系:如果这个锁由读线程持有,而另一个线程请求写入锁,那么其它读线程都不能获得读取锁,直到写线程使用完并释放了写入锁。显然的是,读取锁之间可以相互一起获得,写入锁则一定是独占的。
  • 写线程可以降级为读线程,但读线程不允许升级为写线程(多个读线程都不会放弃自己的读取锁而导致死锁)。

适用场景

当锁的持有时间较长并且大部分操作都不会修改被守护的资源时,那么读-写锁能提高并发性。

如果写操作也很频繁,那可能独占锁更合适一些,因为写操作太多,竞争会很激烈,再加上协调读写锁,性能反而不如独占锁了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值