现在的位置: 首页 > 综合 > 正文

c#中多线程同步解决方案

2012年04月04日 ⁄ 综合 ⁄ 共 2810字 ⁄ 字号 评论关闭
C#中对于多线程编程有很好的支持,常用的有以下几种解决方案:

           1. Lock(object) 对需要同步的代码块加锁;

    2. Monitor Class

    3. ReaderWriterLock Class   

           4. Mutex Class

           5. Semaphore

           6. Event

      这次我主要说一下 Lock 和 Monitor。对于Lock 想必有一定多线程编程经验的程序员都会很熟悉,看名字就知道大概是什么意思了。Lock 就是一把锁,举个很不雅得例子。比如说我们去上WC,当你进去后就要把门锁住,后来的人只能等你方便完了才能进去。

private string lockFlag = "LOCK";
        
public void GoWC(Person p)
        {
            
lock (lockFlag)
            {
                Console.WriteLine(
"Begin");
                  Console.WriteLine(
"End");
            }
        }

 

 

   Lock使用起来非常方便,有一点需要注意就是你同步的对象最好是private或private static,因为如果这个同步对象是public或internal,就有可能被其他程序中其他部分的代码获得,这样的话你的lock就失去的作用,也就是说这个WC的钥匙只能有一把,只有进了WC的人才能获得,其他等待的人是没有办法获得的。

  另一个常用的解决方案是使用Monitor class。 monitor class 和lock其实本身没有什么区别,这难免会让人觉得费解,其实不然。对于使用lock关键字来说经常会发生一种让人非常郁闷的事情“Deadlock”,当personA拥有resourceA还需要ResourceB才能完成任务,而PersonB拥有ResourceB还需要ResourceA才能完成任务时,就会发生死锁,而Lock关键字没有任何的超时机制。

      对于Monitor Class 则不同,Monitor Class中有一个TryEnter的方法,参数列表中可以指定超时时间。

 

Code

  private string lockFlag = "LOCK";

        public void GoWC(Person p)
        {
            Monitor.TryEnter(lockFlag, 
100);

            try
            {
                Console.WriteLine(
"Begin");

                。。。。。

                Console.WriteLine("End");
            }
            
finally
            {
                Monitor.Exit(lockFlag);
            }

 

        有的时候也许当一个线程进入一个同步区域后,又在等待另一个获取资源。对于这样的情况,我们可以使用Monitor类的Wait()操作让它先释放锁,让其它线程进入,等待可以获得资源时再重新进入同步区域:

    

    private static object ball = new object();

        static void Main(string[] args)
{
            Thread threadPing 
= new Thread(new ThreadStart(ThreadPingProc));

            Thread threadPong = new Thread(new ThreadStart(ThreadPongProc));

threadPing.Start();

            threadPong.Start();

            threadPing.Join();

            threadPong.Join();

            Console.ReadLine();
        }

        public static void ThreadPingProc()
        {
            Console.WriteLine(
"ThreadPong : Hello!");

            lock (ball)
            {
                
for (int i = 0; i < 5; i++)
                {
                    Console.WriteLine(
"ThreadPong: Pong");

                    Monitor.Pulse(ball);

                    Monitor.Wait(ball);
                }
            }
        }

        public static void ThreadPongProc()
        {
            Console.WriteLine(
"ThreadPing : Hello!");

            lock (ball)
            {
                
for (int i = 0; i < 5; i++)
                {
                    Console.WriteLine(
"ThreadPing: Ping");

                    Monitor.Pulse(ball);

                    Monitor.Wait(ball);
                }
            }
        }
    }

 

 

(这里使用了《C#和.NET2.0实战(中文版)》p108的代码)

结果如下:

 

ThreadPing : Hello!
ThreadPing: Ping
ThreadPong : Hello
!
ThreadPong: Pong
ThreadPing: Ping
ThreadPong: Pong
ThreadPing: Ping
ThreadPong: Pong
ThreadPing: Ping
ThreadPong: Pong
ThreadPing: Ping
ThreadPong: Pong

抱歉!评论已关闭.