多线程基本操作

参考文档:

http://msdn.microsoft.com/zh-cn/library/c5kehkcz(v=vs.100).aspx

http://www.cnblogs.com/chengxingliang/p/3150731.html

 

接触多线程是从lock开始的

 

      在多线程中经常用到的关键字是lock。

       lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区(所谓的临界点指的是:当多个线程访问一个更改对象状态的方法是,因为不知道到底要修改那个状态,将产生不可预知的数据损坏)。

      所以关于多线程的程序设计中找到程序的临界区是很重要的事情。这样才能表现出多线程的意义。

      通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。因为在C#中 public 是为能再当前类以外来访问它,如果锁定了 public 类型数据将导致在外部调用时,由于没有别的线程锁定以后没有释放,导致程序的等待。这往往是我们不想看到的。 msdn 给的建议是: 定义private 对象来锁定,或 private static 对象变量来保护所有实例共有的数据。

 

理解多线程

      理解多线程可以打一个比喻。一个码头向另一个码头输送货物,如果货物比较少的话,一条船就可以搞定了。可是如果货物非常的多,要10条或者更多的船才能运送完。一条船的话是非常浪费时间的,可能要10天才能运送完。要是找10条船的话1天就运完了。代价是你要租9条船。对于操作系统而言,你要租的那9条船就是系统开销了。如果你的系统有剩余的资源,这个买卖是非常值的。

       在多线程实例化的时候都是运用 ThreadStart 的代理,在该代理的声明中需要提供一个无参的,没有返回值的方法。一个线程是基于一个类执行的。当多线程公用一个类里面的公用数据时(由 static 修饰的数据),也会出现和公用代码类似的问题,这种情况就不应该使用lock关键字了(因为 lock 会把整个对象给锁定,这样的话只能等到该线程释放锁,别的方法才能执行,不管这个方法是否是为多线程提供的方法。) 解决这种情况,c#为我们提供了System.Threading 中的一个类 Monitor , Monitor 提供了使线程共享资源的方案。在System.Threading命名空间提供了同步线程的类。这些类包括MutexMonitorInterlockedAutoResetEventManualResetEvent

 

      http://msdn.microsoft.com/zh-cn/library/ms173178(v=vs.100).aspx msdn 中的这个模块,详细的介绍了c#中线程的问题。

操作多线程

      线程是一个开销很大的操作,(msdn原话)为单个资源分配多个线程可能会导致同步问题,线程会被频繁阻止以等待其他线程,从而与使用多线程的初衷背道而驰。多线程特别适用于需要不同资源(例如文件句柄和网络连接)的任务。如非必要,请不要刻意的使用线程。

      在线程中,对于任何一个被Monitor锁定的对象,内存中都保存着与它相关的一些信息,其一是现在持有锁的线程的应用,其二是一个预备队列,队列中保存了已经准备好获取锁的线程,其三是一个等待队列,队列中保存着当前这当前正在等待这个对象状态的队列的引用。当拥有对象锁的线程准备释放锁时,它使用Monitor.Pluse()方法通知等待队列中的第一个线程,于是该线程被转移到预备队列中,当对象锁被释放时,在预备队列中的线程可以立即获取对象锁。

 

      ThreadPool 类解决的线程问题主要是:某个线程一直在等待一个状态的改变,然后给予响应。但是 ThreadPool 中如果创建了一个线程的话,就会导致这个线程一直存在,没有办法取消。

      控制一个线程池是通过 ManualResetEvent 对象来实现的,ManualResetEvent的对象在初始化时可以设置状态,然后一直保持这个状态直到调用它的Reset() 、Set() 方法,将状态设置为 无信号、有信号。当线程池中所有的线程都工作完成以后 ManualResetEvent 将被设置成有信号。

      ManualResetEvent 的另一个方法 WaitOne() 的作用是使当前线程挂起,直到 ManualRestEvent 对象处于用信号状态,然后在线程中调用 ManualRestEvent.WaitOne() 的线程才会重新执行。

 

能力有限,以后慢慢完善……

posted @ 2013-08-14 13:48  liu0076  阅读(199)  评论(0编辑  收藏  举报