我正在编写一个多线程应用程序。
我正在使用 boost::interprocess 类(版本 1.36.0)
本质上,我有工作线程需要在有工作可供他们执行时得到通知。
我尝试了“信号量”和“条件”两种方法。
在这两种情况下,工作线程的 CSwitch(上下文切换)似乎都非常高,例如每秒 600 次切换。
我看了一下代码,它似乎只是检查一个标志(原子地使用互斥锁),然后在下次重试之前产生时间片。
我期待代码使用 WaitForSingleObject 或其他东西。
具有讽刺意味的是,这正是我在决定“正确”使用并使用 Boost 之前的做法!(即使用互斥锁定期检查标志的状态)。唯一的区别是,在我的方法中,我在两次检查之间睡了 50 毫秒,所以我没有高 CSwitch 问题(是的,工作不会在 50 毫秒内开始对我来说很好)。
几个问题:
- 这个“高”的 CSwitch 值重要吗?
- 如果 boost 库使用 CRITICAL_SECTIONS 而不是信号量(我不关心进程间同步 - 所有线程都在同一个进程中),会发生这种情况吗?
- 如果 boost 使用 WaitForSingleObject 会发生这种情况吗?
- Boost 库中是否有另一种使用上述 Win32 等待方法 (WaitForXXX) 的方法,我认为它不会受到此 CSwitch 问题的影响。
更新:这是一个伪代码示例。我不能添加真正的代码,因为它会有点复杂。但这几乎就是我正在做的事情。这只是启动一个线程来执行一次性异步活动。
注意:这些只是插图!此示例中缺少负载,例如,如果您在线程达到“等待”之前调用 injectWork() 它将无法工作。我只是想说明我对 boost 的使用。
用法类似于:
int main(int argc, char** args)
{
MyWorkerThread thread;
thread.startThread();
...
thread.injectWork("hello world");
}
这是使用 boost 的示例。
class MyWorkerThread
{
public:
/// Do work asynchronously
void injectWork(string blah)
{
this->blah = blah;
// Notify semaphore
this->semaphore->post();
}
void startThread()
{
// Start the thread (Pseudo code)
CreateThread(threadHelper, this, ...);
}
private:
static void threadHelper(void* param)
{
((MyWorkerThread*)param)->thread();
}
/// The thread method
void thread()
{
// Wait for semaphore to be invoked
semaphore->wait();
cout << blah << endl;
}
string blah;
boost::interprocess::interprocess_semaphore* semaphore;
};
这是我的“天真”轮询代码:
class MyWorkerThread_NaivePolling
{
public:
MyWorkerThread_NaivePolling()
{
workReady = false;
}
/// Do work asynchronously
void injectWork(string blah)
{
section.lock();
this->blah = blah;
this->workReady = true;
section.unlock();
}
void startThread()
{
// Start the thread (Pseudo code)
CreateThread(threadHelper, this, ...);
}
private:
/// Uses Win32 CriticalSection
class MyCriticalSection
{
MyCriticalSection();
void lock();
void unlock();
};
MyCriticalSection section;
static void threadHelper(void* param)
{
((MyWorkerThread*)param)->thread();
}
/// The thread method
void thread()
{
while (true)
{
bool myWorkReady = false;
string myBlah;
// See if work set
section.lock();
if (this->workReady)
{
myWorkReady = true;
myBlah = this->blah;
}
section.unlock();
if (myWorkReady)
{
cout << blah << endl;
return;
}
else
{
// No work so sleep for a while
Sleep(50);
}
}
}
string blah;
bool workReady;
};
干杯,
约翰