多线程Monitor.TryEnter(有一个聪明的员工找老板。看到老板们在里面都掐成一团乱麻了,算了我还是撩吧)

 

 

 

 

 

  下面代码展示死锁是怎么形成的,以及如何使用Monitor.TryEnter解除死锁

  话不多说,还是直接看代码

     
        先定义一个方法,以便给一会创建的子线程调用
     static
void LockTooMuch(object lock1, object lock2) { lock (lock1)//先锁定第一个对象 { Thread.Sleep(1000);//等待1秒 lock (lock2);//接着锁定第2个对象 } }

 

        static void Main(string[] args)
        {
            object lock1 = new object();
            object lock2 = new object();


            //子线程使用LockTooMuch方法启动(此方法内部准备先锁定对象1,过一秒再锁定对象2,注意是准备!!并不是此时已经锁定了!!)
            //【注意这个语句里锁定的2个对象,不一定优先于下面的主线程】
       //下一句,主线程的语句lock(lock2)会先执行(主线程锁定)
new Thread(() => LockTooMuch(lock1, lock2)).Start(); //主线程先锁定对象2。注意,此时锁定lock2这行代码会先于上面一句执行(主线程总会比上面的子线程先一步执行) //主线程锁定了对象2,而下一步子线程锁定了对象1,等待1秒(这时对象1还被锁定)。此时主线程要锁定对象1(这时对象1被子线程持有)。紧接着子线程要锁定对象2,而这时对象2还被主线程持有。 //所以死锁形成了!!!!!!!!!!! lock (lock2)//主线程锁定了对象2(此时子线程锁定了对象1,并等待1秒(这时对象1还是被锁定)) { Thread.Sleep(1000); Console.WriteLine("Monitor.TryEnter allows not to get stuck, returning false after a specified timeout is elapsed"); if (Monitor.TryEnter(lock1, TimeSpan.FromSeconds(5)))//主线程要锁定对象1(这时对象1被子线程持有)(而且这时子线程要锁定对象2,而这时对象2还被主线程持有) { //Monitor.TryEnter的作用发挥了!!!!!!!等待5秒后超了,此时Monitor.TryEnter会直接返回false,所以不会造成死锁 Console.WriteLine("Acquired a protected resource succesfully"); } else { Console.WriteLine("Timeout acquiring a resource!"); } } new Thread(() => LockTooMuch(lock1, lock2)).Start(); Console.WriteLine("----------------------------------"); lock (lock2) { Console.WriteLine("This will be a deadlock!"); Thread.Sleep(1000); lock (lock1) { Console.WriteLine("Acquired a protected resource succesfully"); } } }

总体来说多线程死锁主要是因为多个线程之间相互交叉形成的(想一想没有红绿类的路口,车是怎么堵起来的吧),此时就需要Monitor.TryEnter上场了。

posted @ 2020-02-18 10:03  无聊的蚂蚁  阅读(251)  评论(0编辑  收藏  举报