- 1、本文档共15页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
C——线程冲突你了解多少
C++——线程冲突你了解多少
C++——线程冲突你了解多少
一、什么是线程冲突
线程冲突其实就是指,两个或以上的线程同时对同一个共享资源进行操作而造成的问题。
拿一个经典的例子来说,用一个全局变量做计数器,然后开N个线程去完成某个任务,每个线程完成一次任务就将计数器加一,直到完成100次任务。如果不考虑线程冲突问题,用类似下面的代码去做,则很可能会超额完成任务,线程越多,完成任务次数超出100次的可能性就越大。
伪代码如下:
int count = 0;//全局计数器
void ThreadMethod()//运行在每个线程的方法
{
while( true )
{
if ( count = 100 )//如果达到任务指标
break;//中断线程执行
DoSomething();//完成某个任务
count++;
}
}
//省略线程的创建等代码。
具体的,为什么会超额完成任务的原因在这里我就不赘述了,这个例子在单线程环境中是绝对不会超额完成任务的。
当然,在这个例子中,将count++放到if语句中,也许能降低一些事故发生的概率,但那不是绝对的,换言之这样的程序不能杜绝超额完成任务的可能。
其实从线程冲突的定义中我们不难发现,要造成线程冲突有两个必要条件:多线程和共享资源。这两个条件中有一个不成立,就不可能发生线程冲突问题。
所以,在单线程环境中,是不存在线程冲突的问题的。不过很可惜的是,我们的软件早已进化到了多进程多线程的时代,单线程的程序几乎是不存在的,无论是WinForm还是WebForm,程序运行的环境都是多线程的,而不论你自己是不是明确的开启了一个线程。
既然多线程是不可避免的,那么要避免线程冲突就只能从共享资源来开刀了。
二、线程安全的函数
因为属性和方法都是函数组成的,所以我们探讨一下什么是线程安全的函数。
上面我们说到,线程冲突的必要条件是多线程和共享资源。那么如果一个函数里面没有使用任何可能共享的资源,那么就不可能出现线程冲突,也就是线程安全的。比如说这样的函数:
public static int Add( int a, int b )
{
return a + b;
}
这个函数中所使用的所有的资源都是自己的局部变量,而函数的局部变量是储存在堆栈上的,每个线程都有自己独立的堆栈,所以局部变量不可能跨线程共享。所以这样的函数显然是线程安全的。
但值得注意的是:下面的函数不是线程安全的:
public static void Swap( ref int a, ref int b )
//C++: void Swap( in a, int b )
{
int c = a;
a = b;
b = c;
}
因为ref的存在,使得函数的参数是按引用传递进来的,换言之a和b看起来是函数的局部变量,但实际上却是函数外面的东西,如果这两个东西是另一个函数的局部变量,倒也没有问题,
如果这两个东西是全局变量(静态成员),就不能确保没有线程冲突了。而在上个例子中,a和b在传入函数之时,就做了一个拷贝的动作,所以传进来的a、b到底是全局变量还是静态成员都没有关系了。
同样,这样的函数也不是线程安全的:
public static int Add( INumber a, INumber b )
//C++: int Add( INumber* a, INumber* b );
{
return a.Number + b.Number;
//C++: return a-Number + b-Number;
}
原因在于a和b虽然是函数的内部变量没错,但a.Number和b.Number却不是,它们不存在于堆栈上,而是在托管堆上,可能被其他线程更改。
但只使用局部变量的函数在.NET类库中是很少的,但.NET类库中还是有那么多线程安全的函数,是为什么呢?
因为,即使一个函数使用了共享资源,如果其所使用的共享资源都是线程安全的,则这个函数也是线程安全的。
比如说这样的函数:
private const string connectionString = “…”;
public string GetConnectionString()
{
return connectionString;
}
虽然这个函数使用了一个共享资源connectionString,但因为这个资源是线程安全的,所以这个函数还是线程安全的。
同样的,我们可以得出,如果一个函数只调用线程安全的函数,只使用线程安全的共享资源,那么这个函数也是线程安全的。
这里有一个容易被忽略的问题,运算符。并不是所有的运算符(尤其是重载后的运算符)都是线程安全的。
四、互斥锁
有时候
您可能关注的文档
最近下载
- 2025贵州毕节七星关区实验学校教师“跨校竞聘”60人笔试参考题库附答案解析.docx VIP
- 电机拖动与电气控制 第2版 教案全套 葛芸萍 第1--7章 变压器 ---典型机床电气控制.docx
- 汇川变频器MD320手册.pdf VIP
- 2025贵州毕节七星关区碧阳街道中心校(毕节二十二小)教师“跨校竞聘”34人笔试参考题库附答案解析.docx VIP
- 班主任技能竞赛试题 (2).doc VIP
- 吡啶喹唑啉中间体的合成方法与设计方案.pdf VIP
- 培训资料-子宫内膜增生.ppt VIP
- 2025广东惠州市生态环境局博罗分局和博罗县污染防治攻坚战总指挥部办公室招聘编外人员38人笔试备考试题及答案解析.docx VIP
- 2025贵州七星关区洪山街道中心校(毕节四小)教师“跨校竞聘”工作笔试参考题库附答案解析.docx VIP
- 2025入党积极分子发展对象培训考试题库100题含答案(完整版).docx VIP
文档评论(0)