Java并发[三]

前言

讲解等高级主题

正文

一. 死锁及其避免

  1. 死锁出现的原因通常是出现锁环路造成的, 不管是显示的还是隐式的

  2. 通过定义获取锁的顺序来避免死锁: 通过 System.identityHashCode(object)
    来返回一个锁对象的 Object.hashCode()
    的返回值; 通过这个值来定义锁的顺序, 并在整个应用程序中都按照这个顺序来获取锁, 那么就不会形成锁环路了

Object fromAcct = new Object(); // 这里的锁对象也可以是其他
        Object toAcct = new Object();
        Object tieLock = new Object();
        int fromHash = System.identityHashCode(fromAcct);
        int toHash = System.identityHashCode(toAcct);
        if (fromHash < toHash) {
            synchronized (fromAcct) {
                synchronized (toAcct) {
                    // doSomething
                }
            }
        } else if (fromHash > toHash) {
            synchronized (toAcct) {
                synchronized (fromAcct) {
                    // doSomething
                }
            }
        } else { // 这种情况主要是避免Hash冲突, 此时需要额外的锁
            synchronized (tieLock) {
                synchronized (fromAcct) {
                    synchronized (toAcct) {
                        // doSomething
                    }
                }
            }
        }
  1. 使用开放调用(如果在调用某个方法时, 不需要持有锁, 那么这种调用就被成为开放调用)避免死锁: 这种情况下适用于持有不同锁的方法之间的相互调用(注意锁的级别是在方法上, 而不是代码块上)(相当于形成一个隐式的环); 将锁从方法上转移到需要同步的内部代码块上可以避免死锁

  2. Lock.tryLock()
    : 可以检测死锁和从死锁中恢复过来; 即指定一个超时时限, 在等待超过该时间tryLock()
    会返回一个失败信息

  3. 需要注意的几点:

  1. 对象分配操作的开销比同步的开销更低(实际上, 现在 Java
    的分配操作已经比 C
    语言的 malloc
    调用更快
  2. ConcurrentHashMap
    的以前实现中(现在实现不同咯)采用分段锁, 使用了一个包含 16
    个锁的数组, 每个锁保护散列桶的 1/16
    , 这样就能够支持多达 16
    并发的写入器; ConcurrentHashMap
    中的 size
    将对每个分段进行枚举并将每个分段中的元素数量相加, 而不是维护一个全局计数, 为了避免枚举每个计数, ConcurrentHashMap
    为每个分段都维护了一个独立的计数, 并通过每个分段的锁来维护这个值(这个地方有两点需要注意: 一个是 size
    的计算是在每个 add
    , remove
    操作都会改变一次, 这样虽然增加了 add
    remove
    的操作, 但是这会使得 size
    的计算从 O(n)
    变为 O(1)
    ; 另一个是为每个分段维护一个 size
    , 而不是使用一个全局的共享 size
    , 如果使用一个全局的共享 size
    的话, ,实际上就破坏了分段锁的分段特性, 因为访问共享 size
    的时候, 需要同步)
  • ← Previous Post

原文 

https://husteryp.github.io/2018/11/09/Java并发-三/

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Java并发[三]

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址