2013-12-16 25 views
4

我们有一个支持二进制插件(动态加载库)的应用程序以及一些此应用程序的插件。该应用程序本身是多线程的,插件也可能启动线程。有很多锁定正在进行,以保持数据结构的一致性。多线程环境中的文档锁定

一个主要问题是,有时锁从应用程序调用到插件中。这是有问题的,因为插件代码可能要回调到应用程序中,导致死锁。由于不同的团队在基本应用程序和插件上工作,这个问题更加严重。

问题是:除了编写大量的纯文本之外,是否存在“标准”或至少广泛使用的记录锁定方案的方式?

+0

语言??????? – Ricibob

+0

英文?不,严重的是,我会对描述锁定的语言不可知的方式最感兴趣。如果您有针对特定语言的解决方案,请开火。 – arne

+1

递归锁呢?找到一个可以被同一个线程多次锁定的互斥锁。 – 2014-03-25 17:19:26

回答

3

这是一个理论方法,我希望它能帮助你一点。

对我来说,通过重新设计插件和应用程序通信的方式(如果可能),可以避免这种情况。

插件的代码不安全。为确保应用程序的灵活性和稳定性,您必须构建一种标准方式来交换信息并通过插件进行关键操作。

最简单的方法是避免通过定义无锁api来管理每个特定的插件行为。 要做到这一点,您可以使用环形缓冲区/干扰程序或只是一个动作缓冲区,使插件的关键部分异步。

编辑

很抱歉,如果我以同样的方式再次争论,但这似乎对我来说就像一个“IO”的问题。

对某些资源(内存/磁盘/网络....不知道哪些资源)以及是否需要以高可用性对其进行公开访问。最后,这些资源无法在未锁定您的应用程序的情况下随机访问。

由于经理致力于关键部件,所以等待时间可以足够短以致不可察觉。

但是,这并不容易适用于已经存在的应用程序,大多数情况下,如果它是一个大的应用程序。

如果你还不知道这种东西,我鼓励你看看“干扰者”。对我而言,每次使用线程时都要考虑现代基础知识之一。

+0

嗯,这本身就是一个很好的方法,但是无锁是不可行的,因为从插件返回到主应用程序的有问题的调用主要是查询插件不能等待的信息。 – arne

2

我建议使用简单易学的Petri网,并且可以很好地描述软件不同部分之间的合作。在这个问题中描述了几个有用的文件并发性的模型和工具:https://stackoverflow.com/questions/164187/what-tools-diagrams-do-you-use-for-modelling-multithreaded-systems。您可以根据需要选择合适的型号。

+0

这似乎是最好的方法,但我担心为软件系统写下Petri网将会相当混乱。 – arne

+0

我知道,不幸的是每个模型都有一些优点和缺点。 我的建议是限制使用Petri Net来描述对共享资源的访问,或者一般来说描述生产者 - 消费者之类的合作。为了描述线程之间的同步,您可以使用UML活动图,它非常好,易于理解。 –

2

如果您的锁定方案足够简单以至于您可以在文档中描述它,那么通过所有方式都可以这样做。但是,如果在实践中发生死锁,问题可能不是缺少文档,但API不能满足插件作者的需求。记录限制是一个好的第一步,但消除这些限制会更好。

考虑对你的代码举行,由插件请求一个锁死锁的可能性:

  1. 你的代码是不是在读取或写入中间,但仍持有该锁只是因为这就是代码的写法。在这种情况下,你的代码在调用插件之前应该释放锁。
  2. 您的代码和插件都读取数据,并使用锁来防止并发作者。在这种情况下,请使用读写器锁定。
  3. 您的代码正在更改数据,插件想要读取它。这通常不安全;毕竟,你使用锁来保护整个修改是有原因的。在实践中,大多数尝试使此安全失败(这与编写无锁代码一样困难)。在这种情况下,最好的做法是更改设计,以便在调用插件之前代码完成更改,或者在调用插件后开始更改。
  4. 您的代码正在读取数据,插件想要更改它。就像之前的情况一样,这也是不安全的。你的代码应该在调用插件之前释放锁,然后再次获取它,并假定数据已经改变,重新读取任何你需要继续的内容。

这是最好的建议,我可以在不了解任何关于您的应用程序及其特定需求的更多信息。

对于大多数应用程序,软件公司在相同的过程中回避第三方二进制插件,因为当出现问题时,很难找出原因。用户通常责怪应用程序,而不是插件,并且对应用程序质量的看法很差。可以通过与插件作者保持非常密切的关系来工作,通常包括交换所有源代码(可选地在限制性许可证或NDA下)。

+0

尽管这并没有回答这个问题(我明确地询问了文档工具/技术),但它仍然考虑了一些优点。感谢您的洞察力。 – arne

1

是的,有一个标准的方式来记录在大学使用的锁定方案。 1 /使用图表 您必须绘制图表。图中的每个点都是到其他线程的锁定链接。

ex: T1  T2 
    1 -R-> A 
    2 <-W- B 

2 /使用表 你必须在每个点和线写在每一行

ex: T1   T2 
    lockX(A) lockS(B) 
    read(A) read(B) 
    A<-A50  unlock(B) 

的结论是:这是非常复杂的任务,需要很多时间来追查。

+0

简单但可能相当有效。 – arne