2014-04-15 34 views
1

假设我有3个线程:A,B和C.线程B是一个关键线程,需要尽可能快,而其他两个线程不是同样重要。由于性能原因,我也不使用任何互斥锁。C++ - 将数据复制到2个不同线程的最快/可靠方法

我收到线程A中对象的更新。它是一个在堆上分配的对象。线程A通过将事件发布到线程B的事件队列将此数据传输到线程B.线程B将通过清除旧内存并将指针重置为新内存来更新其对象的副本。现在有一个第三个线程(线程C),每当线程A收到更新时也需要这个数据。

如果我试图将这些数据从线程B转移到线程C,那么在理论上,线程B可能会在线程C正在处理该块内存的同时清除旧内存(这会导致竞争条件)。如果线程C正在处理一组旧数据,那么就可以了。我只是想防止比赛条件。所以在这种情况下,我应该让线程A创建2个数据副本(一个用于线程B,另一个用于线程C)并将事件发布给它们中的每一个?我不想在线程B中创建副本,因为该线程需要尽可能快。

+0

这一切都取决于你的线程实现。你在用什么(例如:pthreads,MPI,OpenMP)? – Cramer

+0

为什么要复制?也许你应该以另一种方式思考。 – EJP

+0

此外,在很多情况下,互斥/同步是必需的,它们不是一个选项。没有它们,线程B可能会看到队列中有一个新事件,但是该事件在内存中的其他位置分配,这不一定是同步的,因此可能包含任何旧垃圾! – Cramer

回答

0

我不知道我是否完全理解这个问题,如果我错了,请纠正我。

所以这里的问题是线程B和线程C可能在同一块数据上工作,并且您不希望使用锁定考虑性能。

那么为什么不在线程B和线程C之间添加一个DataPool层呢?这个DataPool将预分配足够的内存,并且你的线程B会要求它提供新的内存。一旦完成,线程B将指针传递给阻塞队列,并且线程C将开始处理它。一旦线程C完成,它将调用DataPool进行回收。

线程B可能会等待线程C,因为DataPool没有任何可用内存,并且每个人都在等待线程C调用DataPool来释放内存。首先,您可以放大dataPool并测试避免该问题的最佳尺寸。其次,如果线程C不是那么重要,DataPool可以强制线程C终止并获得一些空闲内存。

1

我不是100%确定问题是什么。如果是关于内存管理(即何时释放内存),只需使用shared_ptr(C++ 11或boost)即可。然后去掉指针的最后一个线程将释放内存。

此外,你声称你没有任何互斥体,但你使用的是一个事件队列。该事件队列中有一个互斥量。如果它对你来说足够快,那么很可能在正确的地方也会有一个互斥体。

+0

注意:不要在你的答案上签名,你的名字已经出现;)除此之外,是什么让你认为事件队列有一个互斥体?在那里有无数的无锁队列实现! –

相关问题