在Windows / C ++下,如果我有一个结构:
struct ListItem {
ListItem* next;
ListItem* prev;
...
}
与在主进程和几个动态加载的DLL中运行的多个线程一起,并且所有这些线程需要共享上述结构,如何阻止它们相互踩踏?类似的东西:
ListItem* list = ...
A
list->next = ...
B
我在A和B上放置什么以防止一次运行list->next = ...
一个线程不超过一个?
答案 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)
您正在寻找同步。看一下互斥锁。
http://www.relisoft.com/win32/active.html
http://msdn.microsoft.com/en-us/library/ms684266(v=vs.85).aspx
http://www.installsetupconfig.com/win32programming/threadprocesssynchronizationapis11_42.html
答案 3 :(得分:0)
根据您需要的结构,您可以使用一些无锁数据结构,例如Win API interlocked SList。这种方式即使多个线程正在执行操作,数据结构仍然是一致的。