C++——线程冲突你了解多少.docVIP

  1. 1、本文档共15页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 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,但因为这个资源是线程安全的,所以这个函数还是线程安全的。 同样的,我们可以得出,如果一个函数只调用线程安全的函数,只使用线程安全的共享资源,那么这个函数也是线程安全的。 这里有一个容易被忽略的问题,运算符。并不是所有的运算符(尤其是重载后的运算符)都是线程安全的。 四、互斥锁 有时候

文档评论(0)

f8r9t5c + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

版权声明书
用户编号:8000054077000003

1亿VIP精品文档

相关文档