pthread 的 Win32 替代方案
Posted
技术标签:
【中文标题】pthread 的 Win32 替代方案【英文标题】:Win32 alternative to pthread 【发布时间】:2014-01-21 06:48:32 【问题描述】:是否可以使用标准的 win32 CreateMutex 样式代码编写此代码。我只是想知道我是否想在我们的应用程序中引入一个新库,或者我是否可以找到一种自己编写的方法。我只是不知道如何在关键部分中等待。这是我当前使用 pthread 库的工作代码。
T remove()
pthread_mutex_lock(&m_mutex);
while (m_queue.size() == 0)
pthread_cond_wait(&m_condv, &m_mutex);
T item = m_queue.front();
m_queue.pop_front();
pthread_mutex_unlock(&m_mutex);
return item;
【问题讨论】:
老实说,我会使用 C++11 中的 thread support library,VC++2012 及更高版本支持。如果您必须自己动手,那么诚实地使用 Windows 原语执行此操作是不值得的。如果您可以将您的安装域限制为 Vista/Server2008 及更高版本,则可以使用Windows Condition Variables,使其更加直接。 仔细考虑 WhozCraig 的建议。在 pre-Vista Win32 上滚动您自己的条件变量支持并非易事:cs.wustl.edu/~schmidt/win32-cv-1.html 我坚持支持 MSVC 6.0 和 MSVC 2010,所以它不是一个选项。但是,我可以使用 pthread 库,但想确保我没有错过一些简单的替代方案。我不是你的cmets。 风格说明:避免使用size() == 0
测试空虚;并非所有容器都提供 O(1) size()
,这就是为什么有 empty()
- 它不 [总是] 只是一个捷径。另外,在我看到您不能使用 C++11 之前,我将您的代码转换为 std::thread,请参见此处:pastebin.com/aVzJL1ag
【参考方案1】:
对于 VC-2012 之前的支持,最好的替代方案是支持条件变量的 Boost.Thread。
【讨论】:
我想是时候学习 Boost 了……但也许以后……再加上 Boost.Thread 仍然是一个额外的 dll,这是我试图避免的。 在您要求它存在之前,它不在附加 dll 中。默认情况下(至少在 Windows 上)它被编译为静态库。是的,它仍然应该编译,但这需要 5 分钟。 好的,谢谢。不知道那个。真的要找时间驯服Boost兽了……【参考方案2】:这是我的尝试。这不是 win32 中条件等待锁的最佳实现,但我认为它有效。它可以使用仔细的代码审查审查。
一个警告 - 它不一定保证有序的公平性,因为所有等待的线程最初可能会被阻塞以等待事件。此时调度程序将恢复所有线程以继续运行(直到随后的阻塞 EnterCriticalSection 调用),但不一定按照线程到达 remove() 调用开始时的相同顺序。对于大多数只有少数线程的应用来说,这可能没什么大不了的,但这是大多数线程框架所保证的。
其他警告 - 为简洁起见,我省略了检查所有这些 Win32 API 的返回值的重要步骤。
CRITICAL_SECTION m_cs;
HANDLE m_event;
void Init()
InitializeCriticalSection(&m_cs);
m_event = CreateEvent(NULL, TRUE, FALSE, NULL); // manual reset event
void UnInit()
DeleteCriticalSection(&m_cs);
CloseHandle(m_event);
m_event = NULL;
T remove()
T item;
bool fGotItem = false;
while (fGotItem == false)
// wait for event to be signaled
WaitForSingleObject(m_event, INFINITE);
// wait for mutex to become available
EnterCriticalSection(&m_cs);
// inside critical section
// try to deque something - it’s possible that the queue is empty because another
// thread pre-empted us and got the last item in the queue before us
size_t queue_size = m_queue.size();
if (queue_size == 1)
// the queue is about to go empty
ResetEvent(m_event);
if (queue_size > 0)
fGotItem = true;
item = m_queue.front();
m_queue.pop();
LeaveCriticalSection(&m_cs);
return item;
void Add(T& item)
// wait for critical section to become available
EnterCriticalSection(&m_cs);
// inside critical section
m_queue.push_back(item);
SetEvent(m_event); // signal other threads that something is available
LeaveCriticalSection(&m_cs);
【讨论】:
谢谢,这对我来说是最好的答案。适用于 MSVC6.0 和 2012、Win7 和 WinXp! @uncletall - 只要确保您对其进行了适当的测试,并至少对 Init 和 WaitForSingleObject 调用中的调用的返回值进行一些验证。我实际上并没有编译或测试这段代码。我实际上是用我的 Mac-Mini 上的文本编辑器编写的 :)【参考方案3】:Windows Vista 为此类场景引入了新的原生 Win32 Conditional Variable 和 Slim Reader/Writer Lock 原语,例如:
使用临界区:
CRITICAL_SECTION m_cs;
CONDITION_VARIABLE m_condv;
InitializeCriticalSection(&m_cs);
InitializeConditionVariable(&m_condv);
...
void add(T item)
EnterCriticalSection(&m_cs);
m_queue.push_back(item);
LeaveCriticalSection(&m_cs);
WakeConditionVariable(&m_condv);
T remove()
EnterCriticalSection(&m_cs);
while (m_queue.size() == 0)
SleepConditionVariableCS(&m_condv, &m_cs, INFINITE);
T item = m_queue.front();
m_queue.pop_front();
LeaveCriticalSection(&m_cs);
return item;
使用 SRW 锁:
SRWLOCK m_lock;
CONDITION_VARIABLE m_condv;
InitializeSRWLock(&m_lock);
InitializeConditionVariable(&m_condv);
...
void add(T item)
AcquireSRWLockExclusive(&m_lock);
m_queue.push_back(item);
ReleaseSRWLockExclusive(&m_lock);
WakeConditionVariable(&m_condv);
T remove()
AcquireSRWLockExclusive(&m_lock);
while (m_queue.size() == 0)
SleepConditionVariableSRW(&m_condv, &m_lock, INFINITE, 0);
T item = m_queue.front();
m_queue.pop_front();
ReleaseSRWLockExclusive(&m_lock);
return item;
【讨论】:
除非 OP 需要 WinXP 支持,否则我会赞成这个答案而不是我提供的答案。我忘记了 SRW 的东西。好答案!以上是关于pthread 的 Win32 替代方案的主要内容,如果未能解决你的问题,请参考以下文章
有人用过Posix pthread win32库,dll文件
为啥 MinGW 中仍然没有 std::thread、std::promise 和 std::future? win32中promise和futures的替代方案是啥?