(十五)java并发编程--线程的死锁(deadlock)

线程在操作系统使用不同的资源,一般以以下方式使用这些资源。
1)请求一个资源。
2)使用这个资源。
3)释放资源。

1、什么是死锁?

死锁的情况是,一些线程被阻塞,每个线程都拥有一个资源,并且等待另外一个进程以获取另外的一个资源。
想了想类似于生活中的哪些情形,我拥有有一本书(资源使用)叫做《java并发编程》 ,你拥有一本叫《java虚拟机》,我需要你的才能把java理解的更好,你也需要我的书,我们都各自拥有一本,但都需要得到对方的书籍而完成某个“学习线程”,我等待着你使用完你的书籍,你也等待着我使用完我的本书,便互相等待, 形成了死锁。(互相等待对方的资源,形成死循环,也许例子不太恰当)
相同的情形在操作系统中,当两个或者多个线程拥有一些资源,并且等待其他下线程拥有的资源。
例如如下图所示,线程1拥有资源1并且等待被线程2拥有的资源2, 而线程2拥有资源2但是,等待被线程1拥有的资源。
这里写图片描述
出现死锁的四个条件:
互斥:
线程的共享资源,为了线程安全可能需要同步(例如synchronized),也就是同一时刻只能有一个线程使用这个资源。
在某一个时刻这个资源只能被一个线程使用。
拥有锁和等待:
一个线程至少拥有一个资源,并且等待其他资源。
不能强占资源:一个线程不能获取一个资源,除非另外一个线程释放这个资源。
循环等待:
一些线程互相等待对方释放资源,形成死循环。

2、解决死锁的办法?

1)避免死锁和预防死锁,不让系统陷入死锁状态。
2)忽略死锁问题,如果死锁问题是非常罕见的,就让他发生并重启系统。这是windows和unix广泛采取的方法。
3)

If you need to have multiple locks in your code, make sure everyone always acquire them in the same order.
如果在代码中需要多个锁,确保代码每次请求他们的时候以相同的次序。

避免嵌套锁。只需要所动需要锁定的东西,而不是整个对象,如果符合我们的要求。
下面是典型的死锁例子,如下代码。

package deadlock;

/**
 * `Created by fang on 2017/12/8.
 * 死锁简单示例.伪代码
 */
public class DeadLockDemo {
    public void methodA(){
        synchronized (lockA){
            //.....




            synchronized (lockB){
                //...
            }
        }
    }

    public void methodB(){
        synchronized (lockB){
            //....


            synchronized (lockA){
                //......
            }
        }
    }
}

如上述伪代码,如果被多个线程调用可能会产生死锁。这是因为对象 A B 以不同的次序锁定。
这是绝大多数的死锁的原因,所以想要避免他们,保证这些对象锁是按顺序进行的。

上述代码我们这么解决死锁呢?

上述根源是锁的顺序不对,对共享资源的锁形成了循环等待,我们只需要按照同样的次序锁定就了。
解决方案伪代码如下。

//避免死锁的伪代码.

    public void methodA(){
        synchronized (lockA){
            //.....




            synchronized (lockB){
                //...
            }
        }
    }

    public void methodB(){
        synchronized (lockA){
            //....


            synchronized (lockB){
                //......
            }
        }
    }

我们对对象A B加锁两个方法并一致的锁的次序,解决了死锁问题。

下篇再说一下,死锁的解决方案,生产者和消费者模式。
小思:
自己不要死锁自己,容易死循环,也要多线程,时间分片执行任务。
效率才是王道,如何提高自己的效率? 就是间作,”农作物间作套种方式”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值