改善C#程序的157个建议(连载73)

发表于:2011-11-10 10:07

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:陆敏技    来源:51Testing软件测试网采编

分享:

  也就是说,以上代码锁定的是两个不同的syncObject,这等于完全没有达到两个线程锁定同一个对象的目的。要修正以上错误,只要将syncObject变成static就可以了。

  另外,思考一下lock(this),我们同样不建议在代码中编写这样的代码。如果两个对象的实例分别执行了锁定的代码,实际锁定的也就会是两个对象,完全不能达到同步的目的。

  第二个注意事项:在非静态方法中,静态变量不应作为同步对象。也许有读者会问,前面曾说到,要修正第一个注意事项中的示例问题,需要将syncObject变成static。这似乎和本注意事项有矛盾。事实上,第一个注意事项中的示例代码仅仅出于演示的目的,在实际应用中,我们强烈建议不要编写此类代码。在编写多线程代码时,要遵循这样的一个原则:

  类型的静态方法应当保证线程安全,非静态方法不需实现线程安全。

  FCL中的绝大部分类都遵循了这个原则。像上一个示例中,如果将syncObject变成static,就相当于让非静态方法具备了线程安全性,这带来的一个问题是,如果应用程序中该类型存在多个实例,在遇到这个锁的时候,它们都会产生同步,而这可能不是开发者所愿意看到的。第二个注意事项实际也可以归纳到第一个注意事项中。

  第三个注意事项:值类型对象不能作为同步对象。值类型在传递到另一个线程的时候,会创建一个副本,这相当于每个线程锁定的也是两个对象。因此,值类型对象不能作为同步对象。

  第四个注意事项:锁定字符串是完全没有必要的,而且相当危险。这整个过程看上去和值类型正好相反。字符串在CLR中会被暂存到内存里,如果有两个变量被分配了相同内容的字符串,那么这两个引用会被指向同一块内存。所以,如果有两个地方同时使用了lock(“abc”),那么它们实际锁定的是同一个对象,这会导致整个应用程序被阻滞。

  第五个注意事项:降低同步对象的可见性。可见范围最广的一种同步对象是typeof(SampleClass)。typeof方法所返回的结果(也就是类型的type)是SampleClass的所有实例所共有的,即:所有实例的type都指向typeof方法的结果。这样一来,如果我们lock(typeof(SampleClass)),当前应用程序中所有SampleClass的实例线程将会全部被同步。这样编码完全没有必要,而且这样的同步对象太开放了。

  一般来说,同步对象也不应该是一个公共变量或属性。在FCL的早期版本中,一些常用的集合类型(如ArrayList)提供了公共属性SyncRoot,让我们锁定以便进行一些线程安全的操作。所以你一定会觉得我们刚才的结论不正确。其实不然,ArrayList操作的大部分应用场景不涉及多线程同步,所以它的方法更多的是单线程应用场景。线程同步是一个非常耗时(低效)的操作。若ArrayList的所有非静态方法都要考虑线程安全,那么ArrayList完全可以将这个SyncRoot变成静态私有的。现在它将SyncRoot变为公开的,是让调用者自己去决定操作是否需要线程安全。我们在编写代码时,除非有这样的要求,否则就应该始终考虑降低同步对象的可见性,将同步对象藏起来,只开放给自己或自己的子类就够了(需要开放给子类的情况其实也不多)。

相关链接:

改善C#程序的157个建议(连载1)

改善C#程序的157个建议(连载2)

改善C#程序的157个建议(连载3)

改善C#程序的157个建议(连载4)

改善C#程序的157个建议(连载5)

改善C#程序的157个建议(连载6)

改善C#程序的157个建议(连载7)

改善C#程序的157个建议(连载8)

改善C#程序的157个建议(连载9)

改善C#程序的157个建议(连载10)

改善C#程序的157个建议(连载11)

改善C#程序的157个建议(连载12)

改善C#程序的157个建议(连载13)

改善C#程序的157个建议(连载14)

改善C#程序的157个建议(连载15)

改善C#程序的157个建议(连载71)

改善C#程序的157个建议(连载72)

33/3<123
重磅发布,2022软件测试行业现状调查报告~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2023
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号