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

本文详细探讨了死锁现象,包括线程与数据库事务中死锁的形成原因及解决办法。介绍了锁顺序死锁的概念,并通过示例代码展示了如何通过固定锁顺序避免死锁的发生。此外还讨论了资源等待型死锁的情况及其预防措施。

死锁

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

锁顺序死锁

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

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的资源不够用了,有一个线程的优先级比较低,总有比他高优先级的在运行,就轮不到他。这种问题现在应该基本不会见到了。

活锁

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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值