同步技术之Monitor

C#编译器编译lock语句时,将其编译成了调用Monitor类。

语法如下

if(Monitor.TryEntry(lockObj, 1000))
{
    try
    {
    }
    finally
    {
        Monitor.Exit(lockObj);
    }
}
else
{
    // 超时后的处理代码
}


Monitor.Enter Try 方法之间可能会抛出异常。

例如在线程上调用Abort,或者是OutOfMemoryException

为了解决这个问题CLR 4.0提供了Monitor.Enter的重载,增加了lockTaken 字段,当Monitor.Enter成功获取锁之后,lockTaken就是True,否则为False

我们可以将上面的代码改成下面的版本。

bool lockTaken =  false;
             try
            {
                Monitor.Enter(_locker,  ref lockTaken);
                 //  Do something..
            }
             finally
                 if(lockTaken) {
                    Monitor.Exit(_locker);
                }
            }


Monitor类不仅可以完全取代lock语句(如果只使用lock语句本身的功能,最好还是直接用lock语句吧),还可以使用TryEntry方法设置一个锁定超时,单位是毫秒。

如下面的代码所示:

 class Program
    {
        //在1秒中后,lockObj还未被解锁,TryEntry方法就会返回false,如果在1秒之内,lockObj被解锁,TryEntry返回true。我们可以使用这种方法来避免死锁,如下面的代码所示:
        private static Object objA = new Object();
        private static Object objB = new Object();
        static void Main(string[] args)
        {
            Thread threadA = new Thread(LockA);
            Thread threadB = new Thread(LockB);
            threadA.Start();
            threadB.Start();
            Thread.Sleep(4000);
            Console.WriteLine("线程结束");


        }


        public static void LockA()
        {
            if (Monitor.TryEnter(objA, 1000))//TryEntry方法设置一个锁定超时,单位是毫秒
            {
                Thread.Sleep(1000);
                if (Monitor.TryEnter(objB, 2000))
                {
                    Monitor.Exit(objB);
                }
                else
                {
                    Console.WriteLine("LockB timeout");
                }
                Monitor.Exit(objA);
            }
            Console.WriteLine("LockA");
        }
        public static void LockB()
        {
            if (Monitor.TryEnter(objB, 2000))
            {
                Thread.Sleep(2000);
                if (Monitor.TryEnter(objA, 1000))
                {
                    Monitor.Exit(objA);
                }
                else
                {
                    Console.WriteLine("LockA timeout");
                }
                Monitor.Exit(objB);
            }
            Console.WriteLine("LockB");
        }


    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值