在多个线程之间安全地共享结构

时间:2010-12-14 18:03:34

标签: c++ windows multithreading

在Windows / C ++下,如果我有一个结构:

struct ListItem {
    ListItem* next;
    ListItem* prev;
    ...
}

与在主进程和几个动态加载的DLL中运行的多个线程一起,并且所有这些线程需要共享上述结构,如何阻止它们相互踩踏?类似的东西:

ListItem* list = ...

A

list->next = ...

B

我在A和B上放置什么以防止一次运行list->next = ...一个线程不超过一个?

4 个答案:

答案 0 :(得分:5)

主要有两种方式。一个,可能是最简单的,就是简单地将每个线程发送给它自己的数据结构副本。这样您就不必使用同步来保护数据,因为没有线程共享另一个线程的数据。

但这在很多情况下都不会起作用。有时您确实需要共享一个通用的数据结构。在这种情况下,您需要使用某种形式的同步对象来保护数据结构。 Boost.Threads提供了一些跨平台的,我相信有人会告诉你如何使用它们。由于您专门询问了Windows,我将向您展示Windows方式。

您可以使用CRITICAL_SECTION。首先,在启动工作线程之前,需要初始化主线程中的关键部分:

int main()
{
// ...
  CRITICAL_SECTION cs;
  InitializeCriticalSection(&cs);
// ...
}

然后将指针传递给每个工作线程的cs。 (这是作为一个练习。)在每个工作线程中,在处理数据之前输入cs,并在完成后保留它。

CRITICAL_SECTION* pcs = ...; // passed in from main thread
EnterCriticalSection(pcs); // this will block until the cs is "available"
list->next = ...
LeaveCriticalSection(pcs); // makes the cs available to other threads

以上是psudocode,还有很大的改进空间。例如,临界区应包含在RAII对象中,以便在完成后自动销毁。类似地,锁定和解锁也应该在RAII对象中完成,这样无论你如何退出线程函数,它都会被解锁,即使面对异常也是如此。

您应该注意,CRITICAL_SECTION只能由单个进程使用。如果您需要在多个进程中使用互斥类型对象(而不是您在此处需要的那样),那么您需要使用named mutex代替。

答案 1 :(得分:0)

使用Windows Mutex对象,其中有多个进程可以访问一个资源。

如果您的主题都在一个进程上,那么您可以使用EnterCriticalSection / LeaveCriticalSection。

答案 2 :(得分:0)

答案 3 :(得分:0)

根据您需要的结构,您可以使用一些无锁数据结构,例如Win API interlocked SList。这种方式即使多个线程正在执行操作,数据结构仍然是一致的。