多线程应用中的设计和技术问题

时间:2011-05-20 11:10:46

标签: c++ multithreading

我想讨论与多线程应用程序相关的设计和技术问题/挑战。

我遇到的问题
1.我遇到多个线程正在使用共享函数/变量使应用程序崩溃的情况,因此在那种情况下需要适当的防护。
2.状态机和多线程 -

在深入研究多线程应用程序之前,应该记住几点。 可能存在与1.内存有关的问题2.处理3.套接字等。

请分享您在以下方面的经验

  1. 多线程应用程序中常见的错误是什么
  2. 与多线程相关的任何特定问题。
  3. 我们应该通过值还是通过线程函数中的referen传递数据。

4 个答案:

答案 0 :(得分:1)

人们在多线程应用程序中遇到的最大问题是race conditionsdeadlocks,并且没有使用某种semaphores来保护全局可访问的变量。

答案 1 :(得分:1)

嗯,有这么多......

1)共享函数/过程 - 它们只是代码,除非代码修改自身,否则没有问题。局部变量没有问题,因为每个线程调用一个单独的堆栈,(根据定义,amost)。任何其他数据都可能存在问题,可能需要保护。多任务操作系统上99.99%的家庭API调用都是线程安全的,几乎按照定义。另一张海报已经警告线程本地存储...

2)国家机器。可能有点尴尬。您可以轻松锁定触发到SM的所有事件,从而确保状态的完整性,但是在锁定时不能从SM内部进行阻塞调用(可能看起来很明显,但我已经完成了这一次...... )。

我偶尔只从一个线程运行状态机,将事件对象排队到它。这会将锁定移动到输入队列,这意味着SM更容易调试。它还意味着运行SM的线程可以在内部增量队列上实现超时,因此它本身会激活对增量队列上对象的超时调用(典型示例:具有连接超时的TCP服务器套接字 - 每个需要一个数千个套接字对象独立超时)。

3)'我们应该通过值还是通过线程函数中的referen传递数据。'这里不确定你的意思。大多数操作系统允许在线程创建时传递一个指针 - 按照你的意愿去做。你可以传递一个它应该在工作完成时发出信号的事件或一个等待工作请求的队列对象。创建之后,您需要某种形式的线程间通信来发送请求并获得结果(除非您将使用直接'读/写/ waitForExit'机制 - AV /死锁/无关闭生成器)。

我通常使用简单的信号量/ CS生产者 - 消费者队列来发送/接收工作线程之间的通信对象,并使用PostMessage API将它们发送到UI线程。除了锁定队列,我不需要再锁定。您必须非常努力地使基于消息传递的线程系统死锁,并且线程池之类的东西变得微不足道 - 只需要[no。 (CPU)线程并将每个队列传递给同一队列等待。

常见错误。请参阅其他许多海报,我将添加:

a)直接读取/写入线程字段以传递参数并返回结果,(尤其是UI线程和“工作者”线程之间),即“创建线程挂起,将参数加载到线程字段,恢复线程,等待线程”退出句柄,从线程字段读取结果,自由线程对象'。这会导致不断创建/终止/销毁线程导致性能下降,并且通常会强制开发人员确保在退出应用程序时终止线程以防止关闭时出现AV / 216/217异常。这可能非常棘手,在某些情况下是不可能的,因为一些API无法阻止它们。如果开发人员停止这种讨厌的做法,应用程序关闭问题就会少得多。

b)尝试以程序化方式构建多线程应用程序,例如。试图等待UI事件处理程序中的工作线程的结果。构建线程请求对象,使用参数加载它,将其排入工作线程并退出事件处理程序更安全。线程可以获取对象,做工作,将结果放回到对象中,(在Windows上,无论如何),PostMessage对象返回。 UI消息处理程序可以处理结果并处理对象(或回收,重用:)。这种方法意味着,由于UI和worker总是在不同的数据上运行,这些数据可以比它们都更长,所以没有锁定,并且(通常),不需要确保在关闭应用程序时释放工作线程,(这是问题所在ledgendary)。

RGDS, 马丁

答案 2 :(得分:0)

使用线程锁时,您将面临这些问题。 僵局 优先级倒置 顾海波 “异步信号安全” 耐久性可用性 抢占容忍度 整体表现

如果你想看看更高级的线程技术,你可以看一下无锁线程,其中很多线程在等待的情况下处理同样的问题。

答案 3 :(得分:0)

由于缺乏正确的同步,缓冲区溢出(即使可能因内存损坏而发生),线程本地存储使用不当导致死锁,内存损坏(共享资源)是最常见的事情

此外,它还取决于您使用哪种平台和技术来实现该线程。对于例如在Microsoft Windows中,如果使用MFC对象,多个MFC对象实际上不能跨线程共享,因为它们严重依赖线程本地存储(例如CSocket,CWnd类等)。