显式锁

显式锁

ReentrantLock并不是一种替代内置加锁的方法,而是当内置加锁机制不适用时,作为一种可选择的高级功能。

Lock与ReentrantLock

Lock提供了一种无条件的、可轮询的、定时的以及可中断的锁获取操作,所有加锁和解锁方法都是显式的。

public interface Lock {
    void lock();
    void lockInterruptibly() throws InterruptedException;
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    Condition newCondition();
}

ReentrantLock提供了与synchronized相同的互斥性和内存可见性,同样提供了可重入的加锁语义。但是与synchronized相比,它还为处理锁不可用性问题提供了更高的灵活性。

使用显式锁会更加麻烦一点:必须在finally块中释放锁,否则,如果在被保护的代码中抛出异常,那么这个锁永远无法释放。

轮询锁与定时锁

在内置锁中,在未获取到锁之前会一直阻塞下去,这就容易导致死锁,死锁是个严重的问题,恢复程序的唯一方法是重新启动程序,而防止死锁的唯一方法是在构造程序的时候避免出现不一致的锁顺序。而可定时的与可轮询的锁提供了另外一种选择:避免死锁的发生。可定时的与可轮询的锁获取模式是由tryLock方法实现的,与无条件的锁获取模式相比,它具有更完善的错误恢复机制

可中断的锁获取操作

非块结构的加锁

性能考虑因素

在Java5.0中,当从单线程变化到多线程时,内置锁的性能将急剧下降,而ReentrantLock的性能下降则更为平缓,因而它具有更好的可伸缩性。但在Java6.0中,情况就完全不一样了,内置锁的性能不会因为竞争而急剧下降,并且两者的可伸缩性也基本相当。

公平性

在ReentrantLock的构造函数中提供了两种公平性选择:创建一个非公平的锁(默认)或一个公平的锁。

在公平的锁中,如果有另外一个线程持有这个锁或者有其他线程在队列中等待这个锁,那么新发出请求的线程将会被放入队列中。在非公平的锁中,只有当锁被某个线程持有时,新发出请求的线程才会被放入队列中。

公平锁的缺点

**我们为什么不希望所有锁都是公平的?当执行加锁操作时,公平性将由于挂起线程和恢复线程时存在的开销而极大的降低性能。**在实际情况下,统计上的公平性–确保被阻塞的线程最终能够获得锁,通常已经够用了,并且开销也小得多。在大多数情况下,非公平锁的性能高于公平锁的性能。

在激烈的情况下,非公平锁的性能高于公平锁的性能的一个原因是:在恢复一个被挂起的线程与该线程真正开始运行之间存在严重延迟。这往往意味着,一个线程持有锁的时间非常短,所以可以在被挂起的线程被完全唤醒之前,把锁分配给新发起请求的线程,等到线程被完全唤醒后,获得锁的时刻并没有被推迟,并且吞吐量也获得提高。

使用公平锁的情况

什么时候应该使用公平锁呢?当持有锁的时间相对较长,或者请求锁的平均时间间隔比较长那么应该使用公平锁。在这些情况下,因为“插队”带来的吞吐量提升将会不存在。

synchronized 和 ReentrantLock如何选择

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

未来更可能提高synchronized而不是ReentrantLock的性能。因为synchronized是JVM的内置属性,它能执行一些锁优化,例如锁消除,通过增加锁的粒度来消除内置锁的同步。除非将来需要在Java 5.0 上部署应用程序,否则应该优先使用synchronized。

读-写锁

使用读写锁可以达到这样的效果:一个资源可以被多个读操作访问,或者被一个操作访问,但两者不能同时进行。

**对于在多处理器系统上被频繁读取的数据结构,读写锁能够提高性能。**而在其他的情况下,读-写锁的性能要比独占锁的性能略差一些,这是因为他们复杂度更高。

写线程可以降级为读线程是可以的,当时从读线程升级为写线程是不允许的,因为读线程可以有多个,可能都不会释放读取锁,导致死锁。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值