首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >一个单元在哪个级别测试无锁代码?

一个单元在哪个级别测试无锁代码?
EN

Stack Overflow用户
提问于 2019-01-27 15:54:29
回答 1查看 156关注 0票数 4

LLVM, QEMU, GDB, 博克斯, OpenStack等可以用于在开放源码平台上测试无锁并发代码吗?有人做到了吗?

如果您用推荐软件,回答,我不介意,但我提到LLVM、QEMU和其他,因为这些功能在不同的级别。我想知道在哪一级的实际成功已经发现在交错线程在单元测试控制下。

顺便说一句,我知道旋转/Promela,。这是一个很好的软件,但据我所知,不能将C++、Rust等编译到SPIN/Promela目标上。

如果您知道任何现有的、开源的、无锁并发代码单元测试的例子,都会很高兴地收到。(如果我知道去哪里找的话,我会把资料拿来研究的。)

(另见这些 问题及其答案。)

示例

据我所知,我的问题不需要一个例子,所以你可以忽略这个例子。但是,如果一个可测试的无锁代码的示例对讨论有帮助,下面是C++中一个相对简短的玩具示例。我没有单元测试。

代码语言:javascript
复制
#include <atomic>
#include <thread>
#include <cstdlib>
#include <iostream>

const int threshold     =  0x100;
const int large_integer = 0x1000;

// Gradually increase the integer to which q points until it reaches the
// threshold.  Then, release.
void inflate(std::atomic_bool *const p_atom, int *const q)
{
    while (*q < threshold) ++*q;
    p_atom->store(true, std::memory_order_release);
}

int main()
{
    std::atomic_bool atom{false};
    int n{0};

    // Dispatch the inflator, letting it begin gradually, in the background, to
    // inflate the integer n.
    std::thread inflator(inflate, &atom, &n);

    // Waste some time....
    for (int i = large_integer; i; --i) {}

    // Spin until the inflator has released.
    {
        int no_of_tries = 0;
        while (!atom.load(std::memory_order_acquire)) ++no_of_tries;
        std::cout << "tried " << no_of_tries << " times" << std::endl;
    }

    // Verify that the integer n has reached the threshold.
    if (n == threshold) {
        std::cout << "succeeded" << std::endl;
    }
    else {
        std::cout << "failed" << std::endl;
        std::cerr << "error"  << std::endl;
        std::exit(1);
    }

    inflator.join();
    return 0;
}

澄清: PETER

@PeterCordes精确地澄清了我的问题:

在某些情况下,某些源代码使用任何合理的编译器编译到安全的x86 asm,但是对于弱排序的ISAs来说不安全,这通常也能够执行原子RMW,而不需要完整的seq-cst内存屏障(用于运行时重新排序;编译时间仍然取决于编译器)。因此,您有两个不同的问题:源代码是否可移植到任意C++11系统,以及您的代码在x86上是否实际上是安全的(如果这是您目前所关心的)。

我对这两个问题都很感兴趣,但我想到的是任意的C++11系统。

通常,您希望编写可移植的正确代码,因为在为x86编译时通常不会再花费任何费用。

参考: C++17标准草案n4659 (6MBPDF)很好地解释了Peter引用的C++11并发模型。见第三节。4.7.1.

德克·赫尔曼·霍曼( DIRK HERRMANN )的查询

@DirkHerrmann问了一个相关的问题:

您询问如何对代码进行单元测试,但我不确定您所描述的是真正的单元测试场景。这并不意味着您不能使用任何所谓的单元测试框架(实际上可以用于所有类型的测试,而不仅仅是单元测试)。请您解释一下测试的目标是什么,也就是您想检查的代码的哪些属性?

你的观点被采纳了。我的测试的目标是可靠地通过C++11并发模型所支持的所有可能的时间错误代码。如果我知道代码是坏的,那么我应该能够编写一个单元测试来不及格它。我的麻烦是:

  • 解线程。如果代码是非线程的,I通常可以组成一个单元测试,以不及格坏代码。
  • 线程。不及格,线程代码更难,但只要互斥协调线程,至少代码运行类似于不同的硬件。
  • 无锁.在特定的硬件上不可能通过坏的、无锁的代码.如果我的坏的、没有锁的代码在你的硬件上运行过一次,而在我的硬件上却从未失败过一次,那该怎么办?一个单元如何测试这样的代码?

我不知道我需要什么真的。如果我的x86 CPU没有提供真正的C++11并发模型,也许我需要一个不存在的CPU的仿真器,它确实提供了一个真正的C++11并发模型。我不确定。

如果我确实为一个不存在的CPU提供了一个真正的C++11并发模型的模拟器,那么我的单元测试(据我所知)将需要在所有可能的合法时间内尝试我的代码。

这不是一个容易的问题。我想知道是否有人解决了这个问题。

更新: CDSCHECKER和RELACY

这次讨论使我调查了各种来源,包括

  • 诺里斯和德姆斯基的CDSChecker,开源软件;以及
  • Vyukov编写的关系种族探测器,开放源码软件,前面讨论过这里。

在这篇文章中,我不知道这些是否回答了我的问题,但它们看起来很有希望。我把它们联系在一起,以供参考和进一步调查。

为了参考的完整性,我还添加了

上面已经有联系了。

EN

回答 1

Stack Overflow用户

发布于 2019-02-23 20:00:42

有趣的问题!

一个单元在哪个级别测试无锁代码?

不满意的答案是:您不能真正测试“无锁并发代码”,正如您所说的那样。

不,等等,你当然可以:用一张纸和一支笔来测试它。试着证明它是正确的。设计级别是测试多线程代码的正确级别。

当然,您可以为您的代码编写单元测试,您确实应该这样做,但是对于所有可能的并发执行场景,几乎没有实现100%覆盖率的方法。

您可以(而且应该)尝试折磨您的代码,在不同的架构上运行它(例如,x86是如此连贯,它将隐藏许多并发问题。在手臂上运行。)。你仍然找不到所有的错误。

最基本的规则是:您不能使用测试来确保多线程代码的任何质量级别(无锁或也可以使用锁)。确保正确性的唯一方法是正式地证明代码的正确性,这通常意味着您有一个非常简单的线程设计,这是非常明显的,每个人都在5分钟内理解它。然后编写相应的代码。

不要误解我的意思:测试是有用的。但多线程却让你无处可寻。

为什么会这样呢?首先,单元测试方法不起作用: Mutexes不作曲。

当您将多线程子系统A和B 100%正确地组合在一起时,结果根本无法保证工作。穆特克斯不作曲。条件变量不构成。线程之间的不变量不构成。只有极少数和非常有限的原语,比如组成线程安全队列。但是单元测试中隔离的测试方面假设事物是组成的,比如函数或类。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54389994

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档