【问题标题】:Code Contracts - nice, on the edge, but not ready for prime time?代码合同——很好,处于边缘,但还没有准备好迎接黄金时段?
【发布时间】:2011-02-08 07:13:34
【问题描述】:

我被 .NET 4 中引入的代码协定深深吸引(尽管在 DevLabs 的帮助下)。但是一张精美的印刷品让我冷静了很多。它是这样说的:

  • 当后置条件在线程安全方法中在锁之外调用时,除了不使用它们之外,目前没有解决此问题的方法。
  • .NET 依赖于二进制重写器,因此构建速度较慢。
  • 使用代码协定也可能会导致运行时性能下降。
  • 不能用于安全敏感检查,因为它们可以在运行时通过处理 ContractFailed 事件来规避。

对我来说最大的是第一个。我不知道是否有人再编写单线程应用程序。所以如果代码契约不能支持多线程,我看不到它们的用途。或者也许我不应该对此感到太大压力,因为后置条件用于断言方法本身的内部,可以进行单元测试。

顺便说一句,我没有找到任何东西,也没有尝试反汇编我的代码来查看先决条件的注入位置。我想在一个简单的方法中,当 lock() 首先出现时,在它之后注入检查很简单,但是在一个相当复杂的方法中,当锁定发生在中间的某个地方时,这可能是一个问题。或者如果使用了 lock() 以外的其他机制。

【问题讨论】:

    标签: c# multithreading .net-4.0 code-contracts


    【解决方案1】:

    您似乎将“编写多线程应用程序”与“使每个类都线程安全”混淆了。撇开tricky question of defining the term "thread safety" 不谈,我建议您的课程中很少有人应该在大多数应用程序中使用锁定。

    通常我会编写很多类,它们不会尝试明确地线程安全,但同样没有任何线程依赖项。他们假设如果你要从多个线程中使用它们,你一次只能从一个线程中使用它们,并使用适当的内存屏障来确保在一个线程中所做的更改在接下来使用它们的任何线程中都是可见的。

    然后有相对少数类执行必要的协调。

    现在,代码契约的问题可能会使这几个类变得足够弱,以至于整个想法都崩溃了……但我不认为一开始就是这样。

    我有点担心代码契约将面临的问题,因为 C# 编译器会做越来越多的工作来重写你的代码......我不知道契约团队是否已经解决了迭代器块的问题,但即使当 C# 5 推出异步方法时,他们将不得不再次这样做......

    【讨论】:

    • 我同意无状态类。但是在处理状态时,类必须是线程安全的。我尽我所能尽量减少它们的数量。在旁注中,我可能更多地考虑黑白或全有或全无的方法 - 为什么在某些地方使用代码合同,而不是在其他地方,因为它们的局限性。
    • @Schultz9999:不,只有有状态的类同时从多个线程中使用需要处理这个问题。如果 either 一个类只在一个线程中用于整个请求(例如,StringBuilders 通常不会跨线程使用)或者它们只被一个线程使用,那很好一次线程,具有适当的内存屏障以保持一致性。至于您的第二个问题:基本上,如果这样做可以使您的代码更清晰或更可靠,则仅对 一些 代码使用代码合同。有些代码很难/不可能进行完整的单元测试——但我仍然尽可能地编写测试......这里也是一样。
    • 我同意您关于如何编写代码的回答。也许状态对象本身可以提供一种保持内部线程安全的方法,而处理程序可能不关心锁定,从而允许重写器按预期重新组织代码。这有助于避免问题,但它仍然存在。即使我喜欢这两个帖子,我也会接受另一个答案,但你有无限多的点:)
    【解决方案2】:

    除了不使用它们之外,当在线程安全方法中在锁之外调用后置条件时,目前没有解决此问题的方法。

    其实不是问题——如果您在线程安全方法中的 lock 语句之外进行检查,您也可能会遇到问题。针对这个小小的“限制”调整您的实现。问题是代码重写器如何知道您必须锁定资源?我认为这个限制会持续很长时间。

    .NET 依赖于二进制重写器,因此构建速度较慢。

    是的,必须评估、生成和保存一些 IL 以注入一些 IL 构建新依赖项 = 当然需要更多时间。

    使用代码契约也可能会导致运行时性能下降。

    同样不是异常或问题,更多代码(为代码合约生成)= 更慢。基本上你只有更多的代码,而且你可能通过代理类运行什么,所以有更多的代码+可能的代理。

    不能用于安全敏感检查,因为它们可以在运行时通过处理 ContractFailed 事件来规避。

    是的,不要那样做。您甚至不必禁用/重新组装组件即可跳过潜在的安全检查。如果可能,将任何与安全相关的控制流保留在服务器上(无论是 web 还是 db),或者尝试在本地尽可能地混淆您的代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-13
      • 1970-01-01
      • 2010-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      相关资源
      最近更新 更多