C# lock 学习

  从MSDN上看的例子,加上从网上看到的对于lock的一些解释,自己加以总结注释,记录一下。

  先看代码:

  

class Program
    {
        static void Main(string[] args)
        {
            //实例化线程数组
            Thread[] threads  = new Thread[10];
            //实例化Account对象
            Account acc = new Account(1000);
            //构建十个线程赋值到threads
            for(int i=0;i<10;i++)
            {
                Thread t=new Thread(new ThreadStart(acc.DoTransactions));
                threads[i]=t; 
            }
            //执行线程
            for (int i = 0; i < 10; i++)
            {
                threads[i].Start();
            }
            Console.ReadKey();
        }
    }
    class Account
    {
        //一个只读的Object对象实例,用来锁定
        private readonly  Object thisLock = new Object();
        //用来在构建构造函数时赋值的 金额
        int balance;
        //随即对象
        Random r = new Random();
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="initial"></param>
        public Account(int initial)
        {
            balance = initial;
        }
        /// <summary>
        /// 减金额
        /// </summary>
        /// <param name="amount">要减去的金额</param>
        /// <returns>返回 减去后的金额</returns>
        int Withdraw(int amount)
        {

            if (balance < 0)
                throw new Exception("Negative Balance");
            //lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。 如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
            //这里将 只读的Object对象实例thisLock锁定
            lock (thisLock)
            {
                //要减去的金额大于 账号上的金额
                if (balance >= amount)
                {
                    Console.WriteLine("Balance before Withdrawal :{0}", balance);
                    Console.WriteLine("Amount to Withdraw        : -{0}", amount);
                    balance = balance - amount;
                    Console.WriteLine("Balance after Withdrawal  :{0}", balance);
                    Console.WriteLine("   ");
                    return amount;
                }
                else
                {
                    return 0;
                }
            }
        }
       /// <summary>
        /// 随即获取1-100的值 传给Withdraw()方法
       /// </summary>
        public void DoTransactions()
        {
            for (int i = 0; i < 100; i++)
            {
                Withdraw(r.Next(1, 100));
            }
        }
    }

  MSDN中对于lock的解释:lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。 如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。

  本例中使用了只读的Object对象实例thisLock来执行锁定。比如线程a执行到了lock(thisLock),判断thisLock是否被锁定,得知未被锁定,a锁定thisLock,执行”{}“内的语句。b此时也执行到了这里,得知thisLock已经被锁定了(a正在锁定中),b就等待,直到a执行完,b在执行lock。

  MSDN中讲到lock(this)、lock(type(MyType))、lock(“myLock”)时是会有问题的,现在来说下为什么会有问题。

  lock(this):如果实例可以被公共访问,则出现问题。这里会有两个问题:1>实例可被公共访问时,这里的锁定会导致其他访问不可用。2>这种锁定只能锁定当前实例,对其他实例没用。

  lock(type(MyType)):这种锁定解决了上述情况的第二种问题,但是他出现第一种问题的可能性更大了。

  lock(“myLock”):程序中任何使用“myLock”字符串的地方都会共享这个锁定。

  综上所述,MSDN中给出的最佳做法是“定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。

  所以最佳办法是用 private static readonly Object lockThis=new Object();来锁定。

  private:避免其他地方使用。

  static:可以锁定到所有实例。

  readonly:保证锁定的对象不被修改,否则后面的线程会畅通无阻了。

posted @ 2013-01-22 11:35  小飞的DD  阅读(216)  评论(0编辑  收藏  举报