监视器

监视器

Monitor 对象通过使用 Monitor.Enter、Monitor.TryEnter 和 Monitor.Exit 方法对特定对象进行加锁和解锁来提供同步访问代码区域的功能。 对代码区域加锁之后,可以使用 Monitor.Wait、Monitor.Pulse 和 Monitor.PulseAll 方法。 Wait 在其暂停并等待通知的情况下解锁。 当 Wait 收到通知时,会返回并重新加锁。 Pulse 和PulseAll 都发送信号以继续执行等待队列中的下一个线程。

lock语句使用Monitor.Enter获取锁,使用Monitor.Exit释放锁。使用lock的优点在于块中的所有内容包含在Try语句中,Try语句有一个finally块用于保证锁得以释放。

Monitor将锁定对象(引用类型)而非值类型。如果将值类型传递给Enter和Exit时,它会针对每个调用分别装箱。 由于每个调用都创建一个单独的对象,所以 Enter 从不拦截,此外,传递给 Exit 的对象不同于传递给 Enter 的对象,所以 Monitor 将引发 SynchronizationLockException

虽然您可以在调用 Enter 和 Exit 之前装箱值类型变量,并将相同的装箱对象同时传递给两个方法,但是这样做没有任何好处。 对变量的更改不能在装箱的变量中体现出来,也没有办法更改已装箱的变量的值。

一个Demo:

namespace MyConsole2
{
    class Program
    {
        static Int32 numAsyncOps = 5;
        static AutoResetEvent asyncOpsAreDone = new AutoResetEvent(false);
        static SyncResource SyncRes = new SyncResource();
        static UnSyncResource UnSyncRes = new UnSyncResource();

        static void Main(string[] args)
        {
            for (Int32 threadNum = 0; threadNum < 5; threadNum++)
            {
                //ThreadPool.QueueUserWorkItem(new WaitCallback(SyncUpdateResource), threadNum);
                ThreadPool.QueueUserWorkItem(new WaitCallback(UnSyncUpdateResource), threadNum);
            }

            asyncOpsAreDone.WaitOne();//阻塞当前现在,直到WaitHandler收到信号
            Console.WriteLine("	
All synchronized operations have completed.	
");

            Console.ReadLine();
        }


        static void SyncUpdateResource(Object state)
        {
            // This calls the internal synchronized method, passing
            // a thread number.
            SyncRes.Access((Int32)state);

            // Count down the number of methods that the threads have called.
            // This must be synchronized, however; you cannot know which thread
            // will access the value **before** another thread's incremented
            // value has been stored into the variable.
            if (Interlocked.Decrement(ref numAsyncOps) == 0)
            {
                // Announce to Main that in fact all thread calls are done.
                asyncOpsAreDone.Set();//将事件状态设置为终止状态
            }
        }

        static void UnSyncUpdateResource(Object state)
        {
            // This calls the unsynchronized method, passing a thread number.
            UnSyncRes.Access((Int32)state);

            // Count down the number of methods that the threads have called.
            // This must be synchronized, however; you cannot know which thread
            // will access the value **before** another thread's incremented
            // value has been stored into the variable.
            if (Interlocked.Decrement(ref numAsyncOps) == 0)
            {
                // Announce to Main that in fact all thread calls are done.
                asyncOpsAreDone.Set();
            }
        }

    }
    class SyncResource
    {
        public void Access(Int32 threadNum)
        {
            // Uses Monitor class to enforce synchronization.
            lock (this)
            {
                // Synchronized: Despite the next conditional, each thread
                // waits on its predecessor.
                if (threadNum % 2 == 0)
                {
                    Thread.Sleep(2000);
                }
                Console.WriteLine("Start Synched Resource access (Thread={0})", threadNum);
                Thread.Sleep(200);
                Console.WriteLine("Stop Synched Resource access  (Thread={0})", threadNum);
            }
        }
    }

    // Without the lock, the method is called in the order in which threads reach it.
    class UnSyncResource
    {
        public void Access(Int32 threadNum)
        {
            // Does not use Monitor class to enforce synchronization.
            // The next call throws the thread order.
            if (threadNum % 2 == 0)
            {
                Thread.Sleep(2000);
            }
            Console.WriteLine("Start UnSynched Resource access (Thread={0})", threadNum);
            Thread.Sleep(200);
            Console.WriteLine("Stop UnSynched Resource access  (Thread={0})", threadNum);
        }
    }
}
原文地址:https://www.cnblogs.com/goodlucklzq/p/4487268.html