回顾一下上次,我们讨论了lock/AutoResetEvent/ManualResetEvent以及Semaphore。这些用于线程同步的结构叫做同步基元。同步基元从类型上可以分为锁定/通知/联锁三种。lock显然锁定方式,而且是独占锁定,也就是在锁释放之前不能由其它线程获得。 Semaphore也是一种锁定,只不过不是独占锁,可以指定多少个线程访问代码块。AutoResetEvent和ManualResetEvent当然就是通知方式了,前者在通行之后自动重置,后者需要手动重置。我们还看到了即使使用同步机制不一定能确保线程按照我们规划的去执行,因为从根本上来说,操作系统的线程调度我们是没有办法预测的,除非使用阻塞或锁等待等方式,否则我们很难去预测两个无关的线程究竟哪个先得到执行(即使设置了优先级),而且在使用这些同步机制的时候我们也要考虑到性能问题,如果多线程程序做的不好的话很可能会比单线程执行效率还低,比如我们开启了多个线程相互阻塞等待并没有任何的并行运算,比如在一个多线程环境汇总我们锁的范围很大,导致多线程环境变为了一个单线程环境,有关性能问题以后再讨论,这次我们来看看其它的一些同步基元。
本文的例子基于上文定义的一些基本静态对象:
static int result = 0;
static object locker = new object();
static EventWaitHandle are = new AutoResetEvent(false);
static EventWaitHandle mre = new ManualResetEvent(false);
使用lock保护共享资源不被多个线程同时修改是常见的做法,其实lock本质上基于Monitor,而使用Monitor本身可以带来更丰富的特性,比如可以设置超过某个等待时间段就不继续等待: