显式锁

在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编发编程实战>>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容