下面的表格列展了.NET对协调或同步线程动作的可用的工具:

                      简易阻止方法

构成

目的

Sleep

阻止给定的时间周期

Join

等待另一个线程完成

                      锁系统

构成

目的

跨进程?

速度

lock

确保只有一个线程访问某个资源或某段代码。

Mutex

确保只有一个线程访问某个资源或某段代码。可被用于防止一个程序的多个实例同时运行。

中等

Semaphore

确保不超过指定数目的线程访问某个资源或某段代码。

中等

                    信号系统

构成

目的

跨进程?

速度

EventWaitHandle

允许线程等待直到它受到了另一个线程发出信号。

中等

Wait 和 Pulse*

允许一个线程等待直到自定义阻止条件得到满足。

中等

同步要领

阻止(Blocking)

  当一个线程通过上面所列的方式处于等待或暂停的状态,被称为被阻止。一旦被阻止,线程立刻放弃它被分配的CPU时间,将它的ThreadState属性添加为WaitSleepJoin状态,直到停止阻止。停止阻止由以下任一条件触发:

  • 阻止的条件已得到满足
  • 操作超时(如果timeout被指定了)
  • 通过Thread.Interrupt中断了
  • 通过Thread.Abort放弃了

当线程通过(不建议)Suspend 方法暂停,不认为是被阻止了。

休眠 和 轮询

  调用Thread.Sleep阻止当前的线程指定的时间(或者直到中断):

static void Main() {
Thread.Sleep (0); // 释放CPU时间片
Thread.Sleep (1000); // 休眠1000毫秒
Thread.Sleep (TimeSpan.FromHours (1)); // 休眠1小时
Thread.Sleep (Timeout.Infinite); // 休眠直到中断
}

  确切地说,Thread.Sleep放弃了占用CPU,请求不再被分配时间直到超过某个给定的时间。Thread.Sleep(0)放弃CPU的时间刚刚够其它在时间片队列里的活动线程(如果有的话)被执行。

Thread.Sleep在阻止方法中是唯一的暂停捕获Windows Forms程序的Windows消息的方法,在Windows Forms程序中是一个很大的问题,任何对主UI线程的阻止都将使程序失去相应。因此一般避免这样使用,无论信息获取是否被“技术地”暂定与否。线程类同时也提供了一个SpinWait方法,它使用轮询CPU而非放弃CPU时间的方式,保持给定的迭代次数进行“无用地繁忙”。50迭代停顿大约一微秒,一般取决于CPU的速度和负载。从技术上讲,SpinWait并不是一个阻止的方法:一个处于spin-waiting的线程的ThreadState不是WaitSleepJoin状态,并且也不会被其它的线程过早的中断(Interrupt)。SpinWait很少被使用,它的作用是等待一个在极短时间(可能小于一微秒)内可准备好的可预期的资源,而不用调用Sleep方法阻止线程而浪费CPU时间。不过,这种技术的优势只有在多处理器计算机:对单一处理器的电脑,直到轮询的线程结束了它的时间片之前,一个资源没有机会改变状态,这有违它的初衷。并且调用SpinWait经常会花费较长的时间这本身就浪费了CPU时间。

 阻止 vs. 轮询

线程可以等待某个确定的条件来明确轮询使用一个轮询的方式,比如:

while (!proceed);

或者:

while (DateTime.Now < nextStartTime);

  这是非常浪费CPU时间的:对于CLR和操作系统而言,线程进行了一个重要的计算,所以分配了相应的资源!在这种状态

下的轮询线程不算是阻止,不像一个线程等待一个EventWaitHandle(一般使用这样的信号任务来构建)。

阻止和轮询组合使用可以产生一些变换:

while (!proceed) Thread.Sleep (x); // "轮询休眠!"

 x越大,CPU效率越高,折中方案是增大潜伏时间,任何20ms的花费是微不足道的,除非循环中的条件是极其复杂的。

除了稍有延迟,这种轮询和休眠的方式可以结合的非常好,可能它最大的用处在于程序员可以放弃使用复杂的信号结构来工作了。

使用Join等待一个线程完成

可以通过Join方法阻止线程直到另一个线程结束:

class ThreadDemo {

    static void Main() {

    Thread t = new Thread (delegate() { Console.ReadLine();});

    t.Start();

    t.Join(); // 等待直到线程完成

    Console.WriteLine ("Thread t's ReadLine complete!");

    }

}

  Join方法也接收一个使用毫秒或用TimeSpan类的超时参数,当Join超时是返回false,如果线程已终止,则返回true 。

  Join所带的超时参数非常像Sleep方法,实际上下面两行代码几乎差不多:

Thread.Sleep (1000);
Thread.CurrentThread.Join (1000);

  他们的区别明显在于单线程的应用程序域与COM互操作性:在阻止时,Join保持信息捕获,Sleep暂停信息捕获。

C#多线程实践——线程同步的更多相关文章

  1. C#多线程之线程同步篇3

    在上一篇C#多线程之线程同步篇2中,我们主要学习了AutoResetEvent构造.ManualResetEventSlim构造和CountdownEvent构造,在这一篇中,我们将学习Barrier ...

  2. C#多线程之线程同步篇2

    在上一篇C#多线程之线程同步篇1中,我们主要学习了执行基本的原子操作.使用Mutex构造以及SemaphoreSlim构造,在这一篇中我们主要学习如何使用AutoResetEvent构造.Manual ...

  3. C#多线程之线程同步篇1

    在多线程(线程同步)中,我们将学习多线程中操作共享资源的技术,学习到的知识点如下所示: 执行基本的原子操作 使用Mutex构造 使用SemaphoreSlim构造 使用AutoResetEvent构造 ...

  4. 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLock

    [源码下载] 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLoc ...

  5. 重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEvent, AutoResetEvent

    [源码下载] 重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEve ...

  6. IOS 多线程,线程同步的三种方式

    本文主要是讲述 IOS 多线程,线程同步的三种方式,更多IOS技术知识,请登陆疯狂软件教育官网. 一般情况下我们使用线程,在多个线程共同访问同一块资源.为保护线程资源的安全和线程访问的正确性. 在IO ...

  7. 关于Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇高质量的博文)

    Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇质量高的博文) 前言:在学习多线程时,遇到了一些问题,这里我将这些问题都分享出来,同时也分享了几篇其他博客主的博客,并且将我个人的理解也分享 ...

  8. Java:多线程,线程同步,同步锁(Lock)的使用(ReentrantLock、ReentrantReadWriteLock)

    关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象.本文探讨Lock对象. synchronize ...

  9. MFC——9.多线程与线程同步

    Lesson9:多线程与线程同步 程序.进程和线程是操作系统的重点,在计算机编程中.多线程技术是提高程序性能的重要手段. 本文主要解说操作系统中程序.进程和线程之间的关系,并通过相互排斥对象和事件对象 ...

随机推荐

  1. HTML5 canvas 合成属性

    合成属性 globalAlpha                                设置或返回绘图的当前 alpha 或透明值 globalCompositeOperation       ...

  2. thinkphp3.23整合phpexcel

    HINKPHP3.2.3整合PHPexcel实现数据的导入导出.可以上传excel文件后批量导入到数据库,兼容.xls和.xlsx格式:数据库里的数据可以按照搜索条件和分页导出为excel文件.最近接 ...

  3. 细说PHP优化那些事

    我们在用PHP编程的时候,总是想要使自己的程序占用资源最小,运行速度更快,代码量更少.往往我们在追求这些的同时却失去了很多东西.下面我想讲讲我对PHP优化的理解.优化的目的是花最少的代价换来最快的运行 ...

  4. Java中关于String的split(String regex, int limit) 方法

    今天在对一个String对象进行拆分的时候,总是无法到达预计的结果.呈现数据的时候出现异常,后来debug之后才发现,错误出在String spilt上,于是开始好好研究下这东西,开始对api里的sp ...

  5. 转:MFC创建多线程实例

    作者:http://blog.csdn.net/wangningyu/article/details/4404134 平时在MFC里使用多线程时其实是很方面的,因为微软提供了一个API让我们很方面的去 ...

  6. nodejs定时任务node-schedule

    1:使用npm安装node-schedule模块 npm install node-schedule (1)每隔5分钟执行一次: var schedule = require('node-schedu ...

  7. PHP之mysql笔记

    1:在php中提供了两个用于连接MySQL数据库服务器的函数. (1)int mysql_connect(hostname[:port][:/path/to/socket],user,pass). ( ...

  8. v8 源码获取与build

    最近准备在工作之余研究下v8,下班时间鼓捣了2天,现在终于能下载,能gclient sync了. 刚开始的目的就是跑一个hello world,按照wiki上的例子来: https://github. ...

  9. ASP.NET Web.Config 读资料 (学习笔记)

    refer : http://www.cnblogs.com/fish-li/archive/2011/12/18/2292037.html 上面这篇写很好了. 在做项目时,我们经常会遇到一些资料,我 ...

  10. Sum

    Problem Description XXX is puzzled with the question below: 1, 2, 3, ..., n (1<=n<=400000) are ...