并发编程9-避免活跃度危害

简介: <div class="markdown_views"><h2 id="死锁">死锁</h2><p>线程等待资源,形成一个环路就会造死锁。 <br>数据库中事务也可能造成死锁,但是事务会自动选择一个杀死,保证另外的运行,线程可没有这么自动</p><h3 id="锁顺序死锁">锁顺序死锁</h3><p>直接上代码 <br>这种死锁,只要保持锁的顺序就不会发生

死锁

线程等待资源,形成一个环路就会造死锁。
数据库中事务也可能造成死锁,但是事务会自动选择一个杀死,保证另外的运行,线程可没有这么自动

锁顺序死锁

直接上代码
这种死锁,只要保持锁的顺序就不会发生

public class TestCallable {
    private Object left = new Object();
    private Object right = new Object();

    public void left(){
        synchronized (left){
            synchronized (right){
                // dosomething
            }
        }
    }

    public void right(){
        synchronized (right){
            synchronized (left){
                // dosomething
            }
        }
    }
}

动态锁顺序死锁

如下,因为不能保证传入参数的顺序性:

public class TestCallable {
    public void left(Object left, Object right){
        synchronized (left){
            synchronized (right){
                // dosomething
            }
        }
    }
}

如下可以避免死锁:

public class TestCallable {
    public void left(Object left, Object right){
        if(System.identityHashCode(left) > System.identityHashCode(right)){
            synchronized (left){
                synchronized (right){
                    // dosomething
                }
            }
        }else if(System.identityHashCode(right) > System.identityHashCode(left)){
            synchronized (right){
                synchronized (left){
                    // dosomething
                }
            }
        }else{
            synchronized (this){
                // dosomething
            }
        }
    }
}

另外还有可能协作对象间的死锁。这个就防不胜防了。具体问题需要具体分析。不过其实大多数情况下是没有必要给程序加锁的,也就不会出现问题。

资源等待死锁

线程A用到两个数据库连接,持有一个了,不释放,又去拿另外一个,结果池里面没有了,就会造成死锁。
或者是线程A的运行结束依赖于池中B线程,B线程等待A执行结束才会开始执行,就会造成死锁。

避免死锁

定时锁

用显示锁的tryLock来替代内部锁,超时无法获得锁后会抛出异常,重新交回控制权

其他活跃度危险

饥饿

通常是因为CPU的资源不够用了,有一个线程的优先级比较低,总有比他高优先级的在运行,就轮不到他。这种问题现在应该基本不会见到了。

活锁

尽管不会阻塞,但是任然不能执行,因为其会重复相同的操作,永远忙碌状态。
比如一个线程执行失败,然后被加到队尾,然后又执行,又失败。

相关文章
|
2月前
|
存储 缓存 Java
金石原创 |【JVM盲点补漏系列】「并发编程的难题和挑战」深入理解JMM及JVM内存模型知识体系机制(1)
金石原创 |【JVM盲点补漏系列】「并发编程的难题和挑战」深入理解JMM及JVM内存模型知识体系机制(1)
51 1
|
7天前
|
缓存 并行计算 安全
【并发编程系列一】并发编年史:线程的双刃剑——从优势到风险的全面解析
【并发编程系列一】并发编年史:线程的双刃剑——从优势到风险的全面解析
|
11月前
|
缓存 Java 编译器
并发编程Bug源头
并发编程Bug源头
36 1
|
11月前
|
Java 程序员 开发者
疫情过后,Java开发者如何应对多线程与高并发面试题目?
发某粉丝年前参加某个NB企业的面试题列表: 聊聊synchronized的CPU原语级别实现 有一千万个数,写一个程序进行高效求和 已知2开平方为1.414,如何不用数学库,求开平方的值,精确到小数点儿后面10位 编码实现两个线程,线程A不断打印1-10的数字,要求在打印到第五个数字的时候通知线程B 自定义线程池需要指定哪7个参数,为什么不建议使用JUC内置线程池? 高并发、任务执行时间短的业务怎样使用线程池? 并发不高、任务执行时间长的业务怎样使用线程池? 并发高、业务执行时间长的业务怎样使用线程池? 设计一个12306网站,能够撑住最高百万级别TPS(淘宝最高54万TPS),你该如何实现
|
监控 安全 数据安全/隐私保护
在开源代码的时候该如何避免安全风险的发生?
作为开发者来讲,不管是在实际开发中使用开源项目,还是直接投身于开源的贡献中,关于开源相关的内容想必都有自己独到的见解。开源与开发者息息相关,可能有的开发者会觉得不使用开源项目,自己就与开源无关了?这种想法是片面的,因为就算没有在实际开发中使用开源项目,但是在实际开发中肯定会用到一些第三方的插件,那么能保证这些插件没有用到开源的内容么?所以,开源与每一位开发者都有联系。
231 2
在开源代码的时候该如何避免安全风险的发生?
|
存储 安全 Java
吃透Java线程安全问题(下)
吃透Java线程安全问题(下)
|
安全 Java 调度
吃透Java线程安全问题(上)
吃透Java线程安全问题(上)
|
Prometheus 监控 Cloud Native
面试高频:Go语言死锁与goroutine泄露问题谈论
面试高频:Go语言死锁与goroutine泄露问题谈论
|
缓存 算法 Java
Java并发编程Bug的源头
Java并发编程Bug的源头
92 0
Java并发编程Bug的源头
|
存储 缓存
【高并发】导致并发编程频繁出问题的“幕后黑手”
工作了3年的小菜同学,平时在公司只是做些CRUD的常规工作,这次,出去面试被面试官一顿虐啊!尤其是并发编程的知识简直就是被吊打啊。小菜心有不甘,回来找自己工作经验非常丰富的朋友大冰来帮助自己提升并发编程的知识,于是便有了接下来的一系列小菜学并发的文章。
103 0
【高并发】导致并发编程频繁出问题的“幕后黑手”