多线程分析技术

时间:2016-05-28 05:13:35

标签: multithreading analysis

有没有人知道任何可用于设计/调试线程锁定和解锁序列的分析技术?本质上是一种技术(如真值表)我可以用来证明我的锁序列不会死锁。

这不是通过反复试验编程的问题。

我的特殊问题是读写锁 - 但我在一般意义上问这个问题。我相信,如果存在,那将是一种有用的技术。

我尝试了一个因果图,其中我有盒子和箭头,我可以用它来跟踪控制流程,并解决了我80%的问题。但是,如果有任何意义,当一个线程偷偷通过“指令之间的差距”时,我仍然会在压力测试中偶尔遇到死锁。

总结;我需要的是一些表示问题的方法,以便我可以正式分析互斥锁的重叠。

2 个答案:

答案 0 :(得分:3)

坏消息我害怕。我所知道的技术无法“证明”使用锁来控制对共享内存的访问的系统。通过“证明”,我的意思是你无法通过分析证明程序不会死锁,活锁等。

问题是线程是异步运行的。一旦您开始拥有合理数量的线程和共享资源,事件的可能序列(例如,锁定/解锁共享资源)的数量就是天文数字,并且您无法对每个事件进行建模/分析。

由于这个原因,通信顺序进程是由Tony Hoare在1978年开发的。它是Actor模型的一个发展,它本身在很大程度上解决了这个问题。

演员和CSP

简而言之,在Actor模型中,数据不通过带锁的共享内存进行通信。而是沿着两个线程之间的某种通信信道(例如,套接字或管道)发送副本。这意味着你永远不会锁定内存。实际上,所有内存都是线程专用的,其副本在需要时发送给其他线程。这是一个非常“面向对象”的东西;私有数据(线程拥有的内存),公共接口(在通信通道上发出和接收的消息)。它也是非常可扩展的 - 管道可以成为套接字,线程可以成为其他计算机上的进程。

CSP模型就是这样,除非通信通道不接受消息,除非接收端已准备好读取它。

这一添加至关重要 - 这意味着可以用代数方式分析系统设计 。事实上Tony Hoare为CSP制定了一个过程结石。 CSP上的维基百科页面引用了这一点来证明电子商务系统的设计。

因此,如果一个人正在开发一个严格的CSP系统,就可以通过分析证明它不会死锁等。

真实世界体验

我做了很多CSP(或CSP-ish)系统,它总是很好。我没有做数学,而是用直觉来帮助我避免问题。实际上,CSP确保如果我已经建立了一个可以死锁的系统,它每次都会死锁。所以至少我发现它在开发中,而不是2年后,当一些网络连接比正常情况更加繁忙时。

真实世界选项

对于Actor模型编程,有很多选项。 ZeroMQ,nanomsg,微软的.NET数据流库。

他们都非常好,小心翼翼地建立一个非常好的系统。我非常喜欢ZeroMQ和nanomsg - 它们使得将一堆线程分成不同的计算机上的单独进程变得微不足道,而你根本没有改变架构。如果绝对性能不是必不可少的,那么,例如,Google Protocol Buffers就是一个非常整洁的系统,可以将不同的操作系统,语言和系统整合到您的设计中。

我怀疑用于.NET的MS的DataFlow库移动了对数据的引用的所有者而不是复制它。这应该使它非常高效(虽然我实际上没有尝试过它)。

CSP有点难以接受。通过设置消息缓冲区长度,您几乎可以将ZeroMQ和DataFlow转换为CSP。不幸的是,您无法将缓冲区长度设置为零(这将使其成为CSP)。 MS的文档甚至讨论了通过将队列长度设置为1来实现系统稳健性的好处。

您可以通过链接上的同步消息流在Actor上合成CSP。这很烦人,必须实施。

我经常使用自己的通信框架来获得CSP环境。

我认为有Java库,不知道它们是如何积极开发的。

但是,由于现有代码围绕锁定的共享内存编写,因此调整代码将是一项艰巨的任务。所以....

Kernel Shark

如果您使用的是Linux并且您的内核已经编译了FTRACE,则可以使用Kernel Shark查看系统中发生的情况。与Solaris上的DTRACE,VxWorks上的WindView,MCOS上的TATL类似。

你所做的是运行你的系统,直到它停止,然后很快保存FTRACE日志(它被OS覆盖在循环缓冲区中)。然后,您可以以图形方式查看发生的情况(打开Kernel Shark的进程视图),这可能会提供有关什么以及何时执行的线索。

这可以帮助您诊断应用程序的死锁,这可能会导致您做出正确的事情,但最终您无法通过这种方式证明它是正确的。这并不能阻止你有一个尤里卡时刻,你现在已经知道你已经把它弄好了。

我知道没有相当于Windows的FTRACE / Kernel shark。

答案 1 :(得分:1)

对于广泛的多线程任务,我们可以绘制一个反映资源锁定顺序的图表。如果该图有周期,这意味着死锁很可能。如果没有循环,则永远不会发生死锁。 例如,考虑一下Dining Philosophers的任务。如果每个哲学家先拿左叉,然后是右叉,那么锁定顺序图就是连接所有叉子的环。在这种情况下,死锁是非常可能的。然而,如果一个哲学家改变了他的秩序,那么戒指就变成了一条线,永远不会发生死锁。如果所有的哲学家都改变了他们的顺序,并且所有哲学家都会先采取正确的方法,那么这个图形会再次形成一个环并且死锁是真实的。