C#多线程实践——线程同步
下面的表格列展了.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#多线程实践——线程同步的更多相关文章
- C#多线程之线程同步篇3
在上一篇C#多线程之线程同步篇2中,我们主要学习了AutoResetEvent构造.ManualResetEventSlim构造和CountdownEvent构造,在这一篇中,我们将学习Barrier ...
- C#多线程之线程同步篇2
在上一篇C#多线程之线程同步篇1中,我们主要学习了执行基本的原子操作.使用Mutex构造以及SemaphoreSlim构造,在这一篇中我们主要学习如何使用AutoResetEvent构造.Manual ...
- C#多线程之线程同步篇1
在多线程(线程同步)中,我们将学习多线程中操作共享资源的技术,学习到的知识点如下所示: 执行基本的原子操作 使用Mutex构造 使用SemaphoreSlim构造 使用AutoResetEvent构造 ...
- 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLock
[源码下载] 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLoc ...
- 重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEvent, AutoResetEvent
[源码下载] 重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEve ...
- IOS 多线程,线程同步的三种方式
本文主要是讲述 IOS 多线程,线程同步的三种方式,更多IOS技术知识,请登陆疯狂软件教育官网. 一般情况下我们使用线程,在多个线程共同访问同一块资源.为保护线程资源的安全和线程访问的正确性. 在IO ...
- 关于Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇高质量的博文)
Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇质量高的博文) 前言:在学习多线程时,遇到了一些问题,这里我将这些问题都分享出来,同时也分享了几篇其他博客主的博客,并且将我个人的理解也分享 ...
- Java:多线程,线程同步,同步锁(Lock)的使用(ReentrantLock、ReentrantReadWriteLock)
关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象.本文探讨Lock对象. synchronize ...
- MFC——9.多线程与线程同步
Lesson9:多线程与线程同步 程序.进程和线程是操作系统的重点,在计算机编程中.多线程技术是提高程序性能的重要手段. 本文主要解说操作系统中程序.进程和线程之间的关系,并通过相互排斥对象和事件对象 ...
随机推荐
- javascript模块
//使用模块 template = {}; template.createObj = (function(){ //私有成员 var _age = ""; var _name = ...
- PHP防止SQL注入的方法
[一.在服务器端配置] 安全,PHP代码编写是一方面,PHP的配置更是非常关键. 我们php手手工安装的,php的默认配置文件在 /usr/local/apache2/conf/php.ini,我们最 ...
- 常用的JavaScript正则匹配规则代码收藏,很实用
收集一些常用的JavaScript正则表达式匹配规则,比如匹配电话号码.Email.中文字符.身份证号.邮编.QQ号.过滤空白行.匹配特定数字等.觉得这玩意是很有用的,只不过自己水平菜,老是自己写不出 ...
- 网址测速JS
/*.route_nav li a:hover{background: #3c7f84 url(title.png) no-repeat;border-color:#84a3a5;}*/ .route ...
- Java泛型的基本应用
一.泛型概述 jdk1.5版本以后出现的新特性,用于解决安全问题,是一个安全机制. 好处: 1,将运行时期的问题ClassCastException转到了编译时期. 2,避免了强制转换的麻烦. 什么时 ...
- python爬虫程序
http://blog.csdn.net/pleasecallmewhy/article/details/8922826 此人的博客关于python爬虫程序分析得很好!
- 解决VS2013中“This function or variable may be unsafe”的问题
1.在VS2013中编译代码时出现如上错误信息,下面就介绍下如何解决This function or variable may be unsafe的问题. 2.用VS2013打开出现错误的代码文件 3 ...
- IBM总裁郭士纳总结的四类人
IBM总裁郭士纳总结的四类人, 您属于哪一种呢-欢迎就此话题发表评论 积极采取行动促使事件发生的人 被动接受所发生事件的人 对事件持旁观者心态的人 什么事都不关心的人
- css属性之!important
提升指定样式规则的应用优先权. IE6及以下浏览器有个比较显式的支持问题存在,!important在同一条规则集里不生效.请看下述代码: div { color: #f00 !important; c ...
- BZOJ1725: [Usaco2006 Nov]Corn Fields牧场的安排
1725: [Usaco2006 Nov]Corn Fields牧场的安排 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 400 Solved: 290 ...