扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
今天我接着讨论一个最近我比较喜欢讨论的话题:多线程和数据完整性。我知道,你们中的一些人可能讨厌这个话题,但今天我会从一个全然不同的角度讨论这个问题:责任和道德。不,不是使用一个线程是否符合道德观念……而是说明由谁负责线程安全?
具体来说,到底是由库/类/函数/等程序员,还是使用它的程序员负责呢?或者,从另一个方面来讲,我们全都要在代码将用在一个多线程环境的假设下编写代码,还是认为如果有人处在一个多线程环境下,要由他们来处理锁定、死锁等问题呢?
这确实是一个相当棘手的情形!
一方面,在最底层尽可能粒度地实现线程安全更为容易。考虑这个问题:只有在完全必要时才使用适当系统的类设计员,或使用类试图弄清什么需要锁定和死锁预防等的人,何者更有道理?如果一个类(或函数等)没有标记为线程安全,最终结果往往是,使用者每次在线程中触及它时,都会在可疑的项目上进行排它锁定操作;遵循一种外来哲学:“这是唯一确定的方式。”
在这篇文章中,我将使用一些VB.Net术语(SyncLock,它在C#中叫做锁定,基本上是使用一个监视器来锁定一块代码,把它限制在一个try/catch/finally中,最后从这里退出监视器并释放锁定的方式),但其原理相当通用。
另一方面,使用监视器、互斥和信号量等等根本就不便宜。确实,我所做的大量测试表明,即使是每次运行一个线程,使用VB.Net SyncLock(最简单的锁定方式),也会增加20%至100%的执行时间,这种时间差异取决于CPU基础架构。你真地想每次运行代码时都增加这种管理费用吗?还只是为了下一个程序员没有注意到文档中的“非线程安全”部分,或是没有看到测试中的问题呢?
这就是存在冲突的地方了。一方面,很难让使用它的程序员了解足够的底层代码,知道如何以及在什么地方进行锁定,于是使用了互斥(最昂贵的锁定方法)或SyncLock原子弹。另一方面,库作者也难以了解他们的代码的使用情况,于是他们把所有的访问者、属性等包装在SyncLock中,或执行大量的互斥操作。
单独来看,情况变得更加糟糕。一个类中的共享函数和数据如果不是线程安全的话,结果可能是致命的;在确保锁定时,它的好处是让使用它的程序员避免只有一个引用指向它。于是你已经建立了一个随机发生、几乎难以定位的漏洞。更糟糕的是,可能这些漏洞只会以非常细微的方式,以数据损毁的形式表现出来,而不会让系统崩溃。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者