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

1 c++ windows multithreading

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

struct ListItem {
    ListItem* next;
    ListItem* prev;
    ...
}
Run Code Online (Sandbox Code Playgroud)

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

ListItem* list = ...

A

list->next = ...

B
Run Code Online (Sandbox Code Playgroud)

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

Joh*_*ing 5

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

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

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

int main()
{
// ...
  CRITICAL_SECTION cs;
  InitializeCriticalSection(&cs);
// ...
}
Run Code Online (Sandbox Code Playgroud)

然后将指针传递给每个工作线程的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
Run Code Online (Sandbox Code Playgroud)

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

您应该注意,CRITICAL_SECTION只能由单个进程使用.如果您需要跨多个进程使用互斥类型对象(这里不是您需要的那样),那么您需要使用命名的互斥锁.