Chinaunix首页 | 论坛 | 博客
  • 博客访问: 31897
  • 博文数量: 15
  • 博客积分: 386
  • 博客等级: 一等列兵
  • 技术积分: 185
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-25 15:22
文章分类

全部博文(15)

文章存档

2012年(15)

我的朋友
最近访客

分类: 嵌入式

2012-06-18 13:54:51

线程同步这一方面,因为相对来说用得比较少,每次做多线程相关的问题是都必须重新温习,今天在看异步TCP时,又重新梳理了下。

多线程同步大概有两类:一类是信号量,另一类是互斥,排他

1.信号量

.
 

实例代码如:


点击(此处)折叠或打开

  1. class Program

  2.     {
  3.         private int n1, n2, n3;
  4.         EventWaitHandle myEventWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset); //EventResetMode中有手动和自动设置信号量;

  5.                 //false没默认没有信号,true表示默认有信号。对应的类AutoResetEvent和ManualResetEvent


  6.         static void Main(string[] args)
  7.         {
  8.             Program p = new Program();
  9.             Thread t0 = new Thread(new ThreadStart(p.WriteThread));
  10.             Thread t1 = new Thread(new ThreadStart(p.ReadThread));
  11.            
  12.           
  13.             t1.Start();
  14.             t0.Start();
  15.             Thread t3 = new Thread(new ThreadStart(p.AA));
  16.             t3.Start();
  17.             Console.ReadLine();
  18.         }
  19.         private void WriteThread()
  20.         {
  21.             //允许其他需要等待的线程阻塞

  22.             myEventWaitHandle.Reset(); //获得信号并让其他的wait处理等待状态

  23.             Console.WriteLine("t1");
  24.             n1 = 1;
  25.             n2 = 2;
  26.             n3 = 3;
  27.             myEventWaitHandle.Set(); //允许其他等待的线程继续

  28.         }
  29.         private void ReadThread()
  30.         {
  31.            
  32.             myEventWaitHandle.WaitOne(); //阻塞当前线程,直到收到信号

  33.             Console.WriteLine("{0}+{1}+{2}={3}", n1, n2, n3, n1 + n2 + n3);
  34.         }
  35.         private void AA()
  36.         {
  37.             myEventWaitHandle.WaitOne(); //阻塞当前线程,直到收到信号

  38.             string aa = "";
  39.         }

//AutoResetEvent和ManualResetEvent的区别是在waitone后,自动会变成无信号状态,而手动不会,如下面的实例如果设置成手动,则都可以执行,如果设置成

自动, ReadThread和AA方法有一个方法执行不到,因为waitone在自动获得信号后变成了信号状态。

    }

 

 2.lock关键字

      lock是关键词,它将语句块标记为临界区,确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。方法是获取给定对象的互斥锁,执行语句,然后释放该锁。

      MSDN上给出了使用lock时的注意事项通常,应避免锁定 public 类型,否则实例将超出代码的控制范围

3.Monitor类

 

 lock就是对Monitor的Enter和Exit的一个封装,而且使用起来更简洁,因此Monitor类的Enter()和Exit()方法的组合使用可以用lock关键字替代 

 

另外Monitor类还有几个常用的方法:

      TryEnter()能够有效的解决长期死等的问题,如果在一个并发经常发生,而且持续时间长的环境中使用TryEnter,可以有效防止死锁或者长时间 的等待。比如我们可以设置一个等待时间bool gotLock = Monitor.TryEnter(myobject,1000),让当前线程在等待1000秒后根据返回的bool值来决定是否继续下面的操作。

      Wait()释放对象上的锁以便允许其他线程锁定和访问该对象。在其他线程访问对象时,调用线程将等待。脉冲信号用于通知等待线程有关对象状态的更改。

      Pulse(),PulseAll()向一个或多个等待线程发送信号。该信号通知等待线程锁定对象的状态已更改,并且锁的所有者准备释放该锁。等待线程被 放置在对象的就绪队列中以便它可以最后接收对象锁。一旦线程拥有了锁,它就可以检查对象的新状态以查看是否达到所需状态。

      注意:Pulse、PulseAll和Wait方法必须从同步的代码块内调用。 



点击(此处)折叠或打开

  1. class Program

  2.     {
  3.         private static object objA = new object();
  4.         private static object objB = new object();
  5.         static void Main(string[] args)
  6.         {
  7.             Thread threadA = new Thread(LockA);
  8.             Thread threadB = new Thread(LockB);
  9.             threadA.Start();
  10.             threadB.Start();
  11.             Thread.Sleep(4000);
  12.             Console.WriteLine("线程结束");
  13.             
  14.             Console.ReadLine();
  15.         }
  16.         public static void LockA()
  17.         {
  18.             if (Monitor.TryEnter(objA, 1000))
  19.             {
  20.                 Thread.Sleep(1000);
  21.                 if (Monitor.TryEnter(objB, 2000))
  22.                 {
  23.                     Monitor.Exit(objB);
  24.                 }
  25.                 else
  26.                 {
  27.                     Console.WriteLine("LockB timeout");
  28.                 }
  29.                 Monitor.Exit(objA);
  30.             }
  31.             Console.WriteLine("LockA");
  32.         }
  33.         public static void LockB()
  34.         {
  35.             if (Monitor.TryEnter(objB, 2000))
  36.             {
  37.                 Thread.Sleep(2000);
  38.                 if (Monitor.TryEnter(objA, 1000))
  39.                 {
  40.                     Monitor.Exit(objA);
  41.                 }
  42.                 else
  43.                 {
  44.                     Console.WriteLine("LockA timeout");
  45.                 }
  46.                 Monitor.Exit(objB);
  47.             }
  48.             Console.WriteLine("LockB");
  49.         }
  50.     }
本来未产生死锁的,但什么有个超时时间,所以不会发生死锁

4Mutex 

EventWaitHandle的名字与Mutex差了很多,不过它可是Mutex不折不扣的兄弟——它和Mutex都是WaitHandle的子类,用法也差不多


阅读(482) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~