C# 线程同步之排它锁/Monitor监视器类

一、Monitor类说明,提供同步访问对象的机制。

1.位于System.Threading命名空间下,mscorlib.dll程序集中。

2.Monitor通过获取和释放排它锁的方式实现多线程的同步问题。

3.Monitor实现当前进程内的多线程的同步,和lock语句的功能类似。

4.当前为静态类,使用简单

5.依赖的锁定对象和lock语句中类似,同样需要引用类型、建议私有、只读、静态

定义代码:

    //
    // 摘要:
    //     提供同步访问对象的机制。
    [ComVisible(true)]
    public static class Monitor

二、常用方法说明

1.Enter(obj)方法 在指定对象上获取排它锁。

2.Exit(obj)   释放指定对象上的排他锁。

3.IsEntered(obj) 判断当前线程是否已经持有排它锁

4.TryEnter(object obj, TimeSpan timeout)  在指定的时间量内尝试获取指定对象上的排他锁。

5.Wait(object obj) 释放对象上的锁并阻止当前线程,直到它重新获取该锁。

6.Pulse(object obj) 通知等待队列中的线程锁定对象状态的更改。

7.PulseAll(object obj)  通知所有的等待线程对象状态的更改。

三、示例说明一:

说明:多线程累加数值,解决同步问题

private readonly static object _MyLock = new object();
static int Count = 0;
static void CountAdd()
{
    Monitor.Enter(_MyLock); //获取排它锁
    Count++;
    Console.WriteLine(Count);
    if (Count == 10)
    {
        Count = 0;
    }
    Monitor.Exit(_MyLock); //释放排它锁
}
public static void TestOne()
{
    //启动4个线程,累加Count
    for (int i = 0; i < 4; i++)
    {
        Task.Factory.StartNew(() =>
        {
            while (true)
            {
                CountAdd();
                Thread.Sleep(500 * i);
            }
        });
    }
}

1.如果不使用排它锁处理,会出现数据异常

2.使用锁定结果会正常

四、借助于using(){} 块实现锁定处理

1.此场景在事务处理中可能会用到,保证同一个事务,如果一个线程开启操作,其他线程对当前事务操作等待。

2.此场景对于外部使用,不需要考虑多线程问题

1.继承了IDisposable接口的封装

    class AddHelper : IDisposable
    {

        private readonly static object _MyLock = new object();
        static int Count = 0;
        public AddHelper()
        {
            //启用排它锁
            Monitor.Enter(_MyLock);
        }
        public void AddCount()
        {
            Count++;
            Console.WriteLine(Count);
            if (Count == 10)
            {
                Count = 0;
            }
        }
        public void Dispose()
        {
            //释放排它锁
            Monitor.Exit(_MyLock);
        }
    }

2.调用代码块

public static void TestTwo()
{
    //启动4个线程,累加Count
    for (int i = 0; i < 4; i++)
    {
        Task.Factory.StartNew(() =>
        {
            while (true)
            {
                //如果不使用排他锁处理,会出现数据异常
                //AddHelper _add = new AddHelper();
                //_add.AddCount();

                //将排他锁处理封装
                using (AddHelper _add = new AddHelper())
                {
                    _add.AddCount();
                }
                Thread.Sleep(500 * i);
            }
        });
    }
}

更多参考:

C# lock关键词/lock语句块、线程锁

 C# using 关键字使用整理

 EntiryFramework中事务操作(二)

官方参考:https://msdn.microsoft.com/zh-cn/library/system.threading.monitor.aspx

posted @ 2017-01-16 18:29  天马3798  阅读(3442)  评论(0编辑  收藏  举报