gpt4 book ai didi

multithreading - 实现线程安全

转载 作者:行者123 更新时间:2023-12-03 14:34:47 26 4
gpt4 key购买 nike

问题如何确保我的应用程序是线程安全的?他们是否有任何常规做法,测试方法,要避免的事情,要寻找的事情?

背景我当前正在开发一个服务器应用程序,该应用程序在不同的线程中执行许多后台任务,并使用Indy(使用另一组自动生成的线程进行通信)与客户端进行通信。由于该应用程序应该具有很高的可用性,因此程序崩溃是一件非常糟糕的事情,我想确保该应用程序是线程安全的。无论如何,有时我会发现一段代码抛出从未发生过的异常,并且在大多数情况下,我意识到这是某种同步错误,我忘记了正确同步对象。因此,我的问题涉及最佳实践,线程安全性测试以及类似的问题。

mghie:感谢您的回答!我也许应该更精确一些。明确地说,我了解多线程的原理,在整个程序中使用同步(监视器),并且知道如何将线程问题与其他实现问题区分开。但是,尽管如此,我仍然忘记不时添加适当的同步。仅举一个例子,我在代码中使用了RTL排序功能。看起来像

FKeyList.Sort (CompareKeysFunc);

原来,我必须在排序时同步FKeyList。最初编写那行简单的代码时,我只是没有想到。我想谈的就是这些。在哪些地方容易忘记添加同步代码?如何确保在所有重要位置添加了同步代码?

最佳答案

您不能真正测试线程安全性。您所能做的就是证明您的代码不是线程安全的,但是如果您知道该怎么做,那么您已经知道该如何在程序中修复该特定的错误。问题是您不知道的错误,您将如何编写这些错误的测试?除此之外,线程问题比其他问题更难发现,因为调试行为已经可以改变程序的行为。从一个程序运行到下一个程序,从一台机器运行到另一台机器,事情将有所不同。 CPU和CPU内核的数量,并行运行的程序的数量和种类,程序中发生的事情的确切顺序和时间-所有这些以及更多这些都会影响程序的行为。 [我实际上想将月相和类似的东西添加到此列表中,但是您明白了我的意思。]

我的建议是停止将其视为实现问题,而开始将其视为程序设计问题。无论是否为Delphi编写,都需要学习并阅读所有有关多线程的知识。最后,您需要了解基本原理,并在编程中正确应用它们。操作系统提供了诸如关键部分,互斥,条件和线程之类的基元,并且大多数语言仅将它们包装在它们的库中(这忽略了诸如Erlang等提供的绿色线程之类的东西,但这是一个很好的出发点)。

我想说的是从Wikipedia article on threads开始,然后逐步完成链接的文章。我从亚伦·科恩(Aaron Cohen)和迈克·伍德林(Mike Woodring)的"Win32 Multithreaded Programming"书开始-已经绝版,但也许您可以找到类似的书。

编辑:让我简短地跟进您已编辑的问题。所有对非只读数据的访问都必须正确同步以确保线程安全,并且对列表进行排序不是只读操作。因此很明显,需要在列表的所有访问周围添加同步。

但是随着系统中内核越来越多,常量锁定将限制可以完成的工作量,因此,寻找一种不同的方法来设计程序是一个好主意。一种想法是在程序中引入尽可能多的只读数据-不再需要锁定,因为所有访问都是只读的。

我发现接口(interface)对于设计多线程程序非常有用。可以将接口(interface)实现为仅具有对内部数据进行只读访问的方法,并且如果您坚持使用这些接口(interface),则可以确定不会发生很多潜在的编程错误。您可以在线程之间自由共享它们,并且线程安全的引用计数将确保在最后一个对它们的引用超出范围或分配了另一个值时,可以正确释放实现对象。

您要做的是创建从TInterfacedObject继承的对象。它们实现一个或多个接口(interface),这些接口(interface)全部仅提供对对象内部的只读访问,但是它们也可以提供使对象状态发生变化的公共(public)方法。创建对象时,请同时保留对象类型的变量和接口(interface)指针变量。这样,生命周期管理很容易,因为在发生异常时将自动删除对象。您使用指向该对象的变量来调用正确设置该对象所需的所有方法。这会改变内部状态,但是由于这种情况仅发生在 Activity 线程中,因此没有潜在的冲突。一旦正确设置了对象,您就可以将接口(interface)指针返回到调用代码,并且由于以后无法访问该对象,因此除非通过接口(interface)指针,否则您可以确保只能执行只读访问。通过使用此技术,您可以完全消除对象内部的锁定。

如果需要更改对象的状态怎么办?不需要,您可以通过从接口(interface)复制数据来创建一个新对象,然后再更改新对象的内部状态。最后,将引用指针返回到新对象。

通过使用此功能,您仅需要锁定获取或设置此类接口(interface)的位置。通过使用原子交换功能,甚至可以在不锁定的情况下完成此操作。有关设置接口(interface)指针的类似用例,请参见Primoz Gabrijelcic的this blog post

关于multithreading - 实现线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/564319/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com