• C#死锁示例


    死锁的产生

    什么是死锁:

    所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。 因此我们举个例子来描述,如果此时有一个线程A,按照先锁a再获得锁b的的顺序获得锁,而在此同时又有另外一个线程B,按照先锁b再锁a的顺序获得锁。如下图所示

    产生死锁的原因

    竞争资源

    系统中的资源可以分为两类:

    1. 竞争不可剥夺资源(例如:系统中只有一台打印机,可供进程P1使用,假定P1已占用了打印机,若P2继续要求打印机打印将阻塞)
    2. 是竞争临时资源(临时资源包括硬件中断、信号、消息、缓冲区内的消息等),通常消息通信顺序进行不当,则会产生死锁

    进程间推进顺序非法

    1. 若P1保持了资源R1,P2保持了资源R2,系统处于不安全状态,因为这两个进程再向前推进,便可能发生死锁
    2. 例如,当P1运行到P1:Request(R2)时,将因R2已被P2占用而阻塞;当P2运行到P2:Request(R1)时,也将因R1已被P1占用而阻塞,于是发生进程死锁

    一个死锁的例子

    static void LockTooMuch(object lock1, object lock2)
            {
                lock (lock1)  //锁定lock1对象
                {
                    Thread.Sleep(1000); //线程挂起1s
                    lock (lock2) //试图获取lock2对象的锁定
                    {
                        Console.WriteLine("成功获取到lock2对象的锁定");
                    }
                }
            }
    
            /// <summary>
            /// 造成一个死锁
            /// </summary>
            public static void Test()
            {
                //定义两个锁定对象
                object lock1 = new object();
                object lock2 = new object();
    
                //开启线程
                Thread t1 = new Thread(() => {LockTooMuch(lock1,lock2); });
                t1.Start();
    
                //在主线程中锁定lock2对象
                lock (lock2)
                {
                    Console.WriteLine("这将要产生一个死锁");
                    Thread.Sleep(1000);
                    lock (lock1)  //试图访问lock1
                    {
                        Console.WriteLine("成功获取到lock1对象的锁定");
                    }
                }
            }

    通过Monitor的超时锁定机制避免死锁

    直接使用Monitor类。其拥有TryEnter方法,该方法接受一个超时参数。如果在我们能够获取被lock保护的资源之前,超时参数过期,则该方法会返回 false.

    /// <summary>
            /// 使用Monitor避免死锁
            /// </summary>
            public static void Test2()
            {
                //定义两个锁定对象
                object lock1 = new object();
                object lock2 = new object();
    
                //开启线程
                Thread t1 = new Thread(() => {LockTooMuch(lock1,lock2); });
                t1.Start();
    
                //在主线程中使用Monitor类来锁定lock2对象
                //在主线程中锁定lock2对象
                lock (lock2)
                {
                    Console.WriteLine("使用Monitor.TryEnter避免死锁,有一个超时时间的设定 超时返回false");
                    Thread.Sleep(1000);
                    //设置5s的超时时间
                    if(Monitor.TryEnter(lock1,TimeSpan.FromSeconds(5)))
                    {
                        Console.WriteLine("成功获取到lock1对象的锁定");
                    }
                    else
                    {
                        Console.WriteLine("获取lock1对象失败,");
                    }
                }
            }

    源自:C#多线程学习总结

  • 相关阅读:
    spring事务调用失效问题
    redis的主从、哨兵配置
    Lucene介绍与入门使用
    超详细“零”基础kafka入门篇
    消息队列——RabbitMQ学习笔记
    linux中RabbitMQ安装教程
    JAVA正则
    JAVA String类
    JAVA lang包介绍
    JAVA枚举
  • 原文地址:https://www.cnblogs.com/coce/p/13463665.html
Copyright © 2020-2023  润新知