如何避免死锁你知道吗?死锁产生的原因是什么?

2020-04-16 11:17:55 java常见问答 9155

最近有学习java软件开发的朋友,在去面试java相关岗位的时候据说经常会被问到有关java中死锁的问题。那么想请问感兴趣的朋友们,你们知道如何避免死锁吗?知道在什么情况下会导致死锁的情况发生吗?

其实并发程序一旦死锁,一般我们只能重新启动应用。解决死锁问题最好的办法就是避免死锁。

下面我们一起来看看死锁发生的条件有哪些吧。

首先是互斥,因为共享资源是只能被一个线程占用的;

其次是占有且等待,例如线程 t1 已经取得共享资源 s1,那么在尝试获取共享资源 s2 的时候,不不会释放共享资源 s1的;

还有不可抢占的问题,因为其他线程是不能强行抢占线程 t1 占有的资源 s1的;

最后可能就是循环等待的问题了,比如说线程 t1 等待线程 t2 占有的资源,线程 t2 等待线程 t1 占有的资源

看完以上情况下会发生死锁的问题,下面还是得了解一下避免死锁的方法呢,

我们可以这样看,对于以上 4 个产生死锁的条件,如果说破坏了其中一个条件,那么其实就可以避免死锁的发生了。下面我们一起分析一下:

第一个条件 "互斥" ,是不能被破坏的,因为加锁的目的就是为了保证互斥。

剩下的其他三个条件,我们可以尝试。

首先是一次性申请所有的资源,破坏 "占有且等待" 条件。占有部分资源的线程进一步申请其他资源时,如果申请不到的话,可以主动释放它已经占有的资源,破坏 "不可抢占" 的条件。

其次是破坏 "循环等待" 条件,按序申请资源就可以做到了其实。

最后是使用管理类一次性申请所有的资源,可以破坏 "占有且等待" 条件。示例如下:

package constxiong.concurrency.a023;
import java.util.HashSet;
import java.util.Set;
/**
 * 测试 一次性申请所有的资源,破坏 "占有且等待" 条件示例
 * @author ConstXiong
 * @date 2019-09-24 14:04:12
 */
public class TestBreakLockAndWait
{
    //单例的资源管理类
    private final static Manger manager = new Manger();
    //资源1
    private static Object res1 = new Object();
    //资源2
    private static Object res2 = new Object();
    public static void main(String[] args)
    {
        new Thread(() - >
            {
                boolean applySuccess = false;
                while (!applySuccess)
                {
                    //向管理类,申请res1和res2,申请失败,重试
                    applySuccess = manager.applyResources(res1, res2);
                    if (applySuccess)
                    {
                        try
                        {
                            System.out.println("线程:" + Thread.currentThread()
                                .getName() + " 申请 res1、res2 资源成功");
                            synchronized(res1)
                            {
                                System.out.println("线程:" + Thread.currentThread()
                                    .getName() + " 获取到 res1 资源的锁");
                                //休眠 1秒
                                try
                                {
                                    Thread.sleep(1000);
                                }
                                catch (Exception e)
                                {
                                    e.printStackTrace();
                                }
                                synchronized(res2)
                                {
                                    System.out.println("线程:" + Thread.currentThread()
                                        .getName() + " 获取到 res2 资源的锁");
                                }
                            }
                        }
                        finally
                        {
                            manager.returnResources(res1, res2); //归还资源
                        }
                    }
                    else
                    {
                        System.out.println("线程:" + Thread.currentThread()
                            .getName() + " 申请 res1、res2 资源失败");
                        //申请失败休眠 200 毫秒后重试
                        try
                        {
                            Thread.sleep(200);
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                }
            })
            .start();
        new Thread(() - >
            {
                boolean applySuccess = false;
                while (!applySuccess)
                {
                    //向管理类,申请res1和res2,申请失败,重试
                    applySuccess = manager.applyResources(res1, res2);
                    if (applySuccess)
                    {
                        try
                        {
                            无锡妇科医院哪家好 http: //www.xasgfk.cn/
                                System.out.println("线程:" + Thread.currentThread()
                                    .getName() + " 申请 res1、res2 资源成功");
                            synchronized(res2)
                            {
                                System.out.println("线程:" + Thread.currentThread()
                                    .getName() + " 获取到 res1 资源的锁");
                                //休眠 1秒
                                try
                                {
                                    Thread.sleep(1000);
                                }
                                catch (Exception e)
                                {
                                    e.printStackTrace();
                                }
                                synchronized(res1)
                                {
                                    System.out.println("线程:" + Thread.currentThread()
                                        .getName() + " 获取到 res2 资源的锁");
                                }
                            }
                        }
                        finally
                        {
                            manager.returnResources(res1, res2); //归还资源
                        }
                    }
                    else
                    {
                        System.out.println("线程:" + Thread.currentThread()
                            .getName() + " 申请 res1、res2 资源失败");
                        //申请失败休眠 200 毫秒后重试
                        try
                        {
                            Thread.sleep(200);
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                }
            })
            .start();
    }
}

那么以上就是有关java死锁问所有内容了,如果你还想了解更多java一些知识问答,记得关注本站消息哦。