显式锁

作者: evil_ice | 来源:发表于2017-01-12 23:04 被阅读21次

在Java5.0之前,在协调对共享对象的访问时可以使用的机制有synchronized和volatile.Java5.0增加了一种新的机制:ReentrantLock. ReentrantLock并不是一种替代内置加锁的方法,而是当内置锁机制不适合时,作为一种可选择的高级功能.

一,显示锁Lock和内置锁synchronized

Lock接口定义了一组抽象的加锁操作.与内置加锁机制不同的是,Lock提供了一种无条件的,可轮询的,定时的以及可中断的锁获取操作,所有加锁和解锁的方法都是显式的.

  • 1,Lock接口如下
1, void lock() 
 获取锁。
2, void lockInterruptibly() 
 如果当前线程未被中断,则获取锁。
3, Condition    newCondition() 
 返回绑定到此 Lock 实例的新 Condition 实例。
如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false。
4, boolean  tryLock() 
仅在调用时锁为空闲状态才获取该锁。
5, boolean  tryLock(long time, TimeUnit unit) 
如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。
6, void unlock() 
释放锁。
  • 2,ReentrantLock和内置锁的对比

    • 1)ReentrantLock提供了与内置锁相同的互斥性和内存可见性
    • 2)和内置锁一样,ReentrantLock提供了可重入的加锁语义
    • 3)Lock提供了一种无条件的,可轮询的,定时的以及可中断的锁获取操作,所有加锁和解锁的方法都是显式的,加锁方式更加灵活
  • 3,为什么要创建和内置锁如此相似的显式锁?

    • 1)无法中断一个正在等待获取锁的线程
    • 2)内置锁必须在获取该锁的代码中释放,这就简化了编码工作.但是却无法实现非阻塞结构的加锁规则
    • 3)在内置锁中,防止死锁的唯一办法是在构造程序时避免出现不一致的锁顺序.可定时的与可轮询的锁提供了另外一种选择:避免死锁的发生
    • 4)非块结构的加锁
      在内置锁中,锁的获取和释放等操作都是基于代码块的-----释放锁的操作总是与获取锁的操作处于同一个代码块. 例如ConcurrentHashMap使用的分段锁技术,降低锁的粒度提高代码的可伸缩性就必须要使用非块结构的加锁----Lock
  • 4,内置锁和显示锁的性能
    在Java5.0,ReentrantLock能提供更高的吞吐量.
    但在Java6.0中,二者的吞吐量非常接近

  • 5,ReentrantLock的公平性.
    ReentrantLock的公平性是指线程是否按照他们发出请求的顺序来获取锁

    • 在ReentrantLock的构造函数中提供了两种公平选择:创建一个非公平的锁(默认)或者一个公平的锁.在公平的锁上,线程将按照它们发出请求的顺序来获得锁,但在非公平的锁上,则允许"插队":当一个线程请求非公平的锁时,如果在发出请求的同时该锁的状态变为可用,那么这个线程将跳过队列中所有的等待线程并获得这个锁;

    • 我们为什么不希望所有的锁都是公平的呢?
      当执行加锁操作时,公平性将由于在挂起线程和恢复线程时存在的开销而极大地降低性能.
      但是,如果当持有锁的时间相对较长,或者请求锁的平均时间间隔较长,这种情况下,"插队"带来的吞吐量提升则可能不会出现,那么这时候应该选用公平锁.

  • 6, 在Synchronized和ReentrantLock之间如何选择?

    • 1)与显式锁相比,内置锁更简单,简洁紧凑.仅当内置锁不能满足需求时,才可以考虑使用ReentrantLock
      -2)在java5.0中,内置锁与ReentrantLock相比还有另一个有点:在线程转储中能给出在那些调用帧中获得了那些锁,并能够检测和识别发生死锁的线程.而ReentrantLock则不能.在Java6.0后才支持
      -3)未来更可能提升内置锁而不是显式锁的性能.因为内置锁(synchronzied)是JVM的内置属性,他能执行一些优化,例如对线程封闭的锁对象的锁消除优化,通过增加锁的粒度来消除内置锁的同步.而如果通过基于类库的锁来实现这些功能,则可能性不大.

总之,虽然与内置锁相比,显示的lock更能提供一些扩展功能,有着更高的灵活性. 但ReentrantLock不能完全替代synchronzied,只有synchronized不能满足需求的时候,才应该用他.

二,读写锁ReadWriteLock
 Lock   readLock() 
          返回用于读取操作的锁。
 Lock   writeLock() 
          返回用于写入操作的锁。
  • 在读-写锁实现的加锁策略中,允许多个读操作同时进行,但每次只允许一个写操作.
  • ReentrantReadWriteLock为这两种锁都提供了可重入的加锁语义.
  • ReentrantReadWriteLock在构造时也可以选择一个非公平的锁(默认)和公平的锁.在公平的锁中,等待时间最长的线程将优先后的锁.如果这个锁由读线程持有,而另一个线程请求写入锁,那么其他读线程都不能获得读取锁,知道写线程使用完并且释放了写入锁.(可以认为写优先)
    在非公平的锁中,线程获得访问许可的顺序是不确定的.写线程降级为读线程时可以的,但是从读线程升级为写线程时不可以的(这样会导致死锁);

一个简单的读写锁示例---使用读写锁包装一个Map,让其同步

public class ReadWriteMap<K,V>{
    private Map<K,V> map;
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private ReadLock readLock = lock.readLock();
    private WriteLock writeLock = lock.writeLock();
    
    public ReadWriteMap(Map<K,V> map){
        this.map = map;
    }
    
    public V put(K key, V value){
        try{
            writeLock.lock();
            return map.put(key, value);
        }finally{
            writeLock.unlock();
        }
    }
    
    public V get(K key){
        try{
            readLock.lock();
            return map.get(key);
        }finally{
            readLock.unlock();
        }
    }
}

参考:
<<java编发编程实战>>

相关文章

  • 从 synchronized 到 CAS 和 AQS - 彻底弄

    Java 中的并发锁大致分为隐式锁和显式锁两种。隐式锁就是我们最常使用的 synchronized 关键字,显式锁...

  • 13. 显式锁:Lock接口

    显式锁是自JDK1.5开始引入的排它锁。 显式锁的使用 ReentrantLock(可重入锁) Reentrant...

  • 05.锁机制和条件对象简述

    Java的锁机制主要分内置锁(隐式锁)和显式锁。 内置锁 Java每个对象都有一个内置的锁对象,这些锁对象不需要显...

  • 线程安全,内存可见性,竞态条件,内置锁,显式锁概述

    线程安全,内存可见性,竞态条件,内置锁,显式锁概述 在Java中按照锁的实现方式可以划分为内置锁和显式锁,内置锁有...

  • Android面试知识点(三)*

    1、java里的锁总结(synchronized隐式锁、Lock显式锁、volatile、CAS)[https:/...

  • 显式锁

    在JAVA5.0之前,在协调对共享对象的访问时,有synchronized和volatile两种机制。JAVA5....

  • 显式锁

    在Java5.0之前,在协调对共享对象的访问时可以使用的机制有synchronized和volatile.Java...

  • 显式锁

    Lock接口是语言层面的锁 一、 常用方法 lock()加锁 lockInterruptibly()可中断获取锁的...

  • 3.ReentrantLock核心原理分析

    ReentrantLock核心原理分析 ReentrantLock显式锁,相对于synchronized隐式锁而言...

  • 高并发(13)-显式锁与内置锁

    @TOC 前言 上篇文章讲解了什原子的操作类,今天就讲讲并发中的显式锁与内置锁。 什么是显式锁与内置锁 多线程中,...

网友评论

    本文标题:显式锁

    本文链接:https://www.haomeiwen.com/subject/bssjbttx.html