• 转 Lock(递归函数与死锁) .


    源:http://blog.csdn.net/xuzhiqiang1010/article/details/4987824

    看看以下会不会产生死锁:

    public class A
        {
            private object obj = new object();
            public void Test(int i)
            {
                lock (obj)
                {
                    if (i>10)
                    {
                        i--;
                        Test(i);
                    }
                    else
                    {
                        Console.WriteLine(i);
                    }
                }
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                A a = new A();
                a.Test(15);
                Console.ReadKey();
            }
        }

    你的答案是会产生死锁吗?可以理解,因为也许你以前一直以为外层递归被锁住后,不允许在访问里边的代码快,而由于递归,有需要等待外层递归解锁,所以由此造成死锁,现在才知道这种理解是错误的;结果是永远不会出现死锁,因为lock的本质是对于不同的线程来说的,或者这个所的所有权已经归该现成所有,它可以任意使用该锁;

    说道这里又想多说一点,假如另一个线程在另一个函数里操作同一个obj,这是obj可以被访问吗在锁释放之前,如下代码:

    public class Test
        {
            string name = "Empty";

            public Test()
            {
     
            }

            public string Name
            {
                get
                {
                    return this.name;
                }
                set
                {
                    this.name = value;
                }
            }
        }

        public class A
        {
            Test test = new Test();

            public void OneMethod()
            {
                lock (this.test)
                {
                    Console.WriteLine("one thread come in,sleep for 10 seconds");
                    Console.WriteLine(test.Name);
                    Thread.Sleep(10000);//如果第二个线程可以在锁住期间可以对test对象操作,那么线程二应该在10000毫秒之内已经输出
                    test.Name = "One thread output";
                    Console.WriteLine(test.Name);
                }
            }

            public void TwoMethod()
            {
                Thread.Sleep(100);//为了确保第一个线程先锁住后在操作test对象
                Console.WriteLine("two thread come in");//假如由于线程一锁住test对象而不能对test操作的话,那么要等待10000毫秒
                test.Name = "Two thread output";
                Console.WriteLine(test.Name);
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                A a = new A();
                Thread one = new Thread(new ThreadStart(a.OneMethod));
                Thread two = new Thread(new ThreadStart(a.TwoMethod));
                one.Start();
                two.Start();
                Console.ReadKey();
            }
        }

    其输出结果为:

    one thread come in,sleep for 10 seconds

    Empty

    two thread come in//在第一个线程之间操作

    Two thread output//在第一个线程锁住test对象之中,改变的test。Name属性值,说明锁中test时将可以对test进行操作

    One thread output

    答案是:test对象在别的函数中被锁中时,别的线程在被锁块外是可以对test进行操作的

    假如我把第二个方法代码做如下修改:

    public void TwoMethod()
            {
                Thread.Sleep(100);//为了确保第一个线程先锁住后在操作test对象
                Console.WriteLine("two thread come in");//假如由于线程一锁住test对象而不能对test操作的话,那么要等待10000毫秒
                lock (this.test)
                {
                    test.Name = "Two thread output";
                    Console.WriteLine(test.Name);
                }           
            }

    这时的结果是:

    one thread come in,sleep for 10 seconds

    Empty

    two thread come in//在第一个线程获得锁之间线程二进入了第二方法中的锁之前操作

    One thread output//

    Twothread output//说明锁test被解锁以后才执行

    答案是:一个类中几个方法锁住了同一个对象(该对象必须是引用类型)时,那么第一个获得锁的线程操作,其他线程走到锁对象(哪怕所对象不是在同一个函数中)之前将等待对象被解锁,解锁后才可以进入。打个比喻:test对象相当于一个响应器,lock()锁相当于一个锁,操作系统相当于一个监控器,而一个或多个函数中的锁块相当于一个或多大门,多个线程相当于等在一个或多个大门前的人。假如有任一一个大门被一个人闯进时,那么监控器立即给所有锁上锁lock,锁定所有大门,不准任何人进,直到该人出来,监控器自动打开所有锁,所有大门打开,重复执行第一步,监控器保证只有一个人进入某一个大门。当然如果某一个响应器没有lock,就相当于大门没有锁,就可以对test操作,这种情况就是上一种现象

  • 相关阅读:
    __doPostback在客户端控件中的作用
    BlogEngine学习二:基于ICallbackEventHandler的轻量级Ajax方式
    JS操作XML数据备忘
    JS解析DataSet.GetXML()方法产生的xml
    JS中的prototype的使用方式
    实体类的二进制序列化
    PostgreSQL的.NET驱动程序Npgsql中参数对象的一个Bug
    PDF.NET的SQL日志
    PostgreSQL的PDF.NET驱动程序构建过程
    使用XSD编写具有智能提示的XML文件(以SQLMAP脚本为实例)
  • 原文地址:https://www.cnblogs.com/sail/p/2485803.html
Copyright © 2020-2023  润新知