C++ C+中的线程同步+;,以较少的开销
考虑以下代码,这将是我问题的一个最小示例:C++ C+中的线程同步+;,以较少的开销,c++,multithreading,boost,boost-thread,C++,Multithreading,Boost,Boost Thread,考虑以下代码,这将是我问题的一个最小示例: class TaskMgr { public: // This is a threadsafe and lockfree queue implementation static concurrent_list_impl<std::string> Tasks; std::atomic<bool> mRun; std::atomic<bool> mStart; public: TaskMgr
class TaskMgr {
public:
// This is a threadsafe and lockfree queue implementation
static concurrent_list_impl<std::string> Tasks;
std::atomic<bool> mRun;
std::atomic<bool> mStart;
public:
TaskMgr() {mStart = mRun = false;}
~TaskMgr() {}
void run() {
mStart = true;
while (!mEnd) {
//PROCESS QUEUE TASKS
std::string task;
while (Tasks.try_dequeue(task)) {
// DO STH WITH TASK
}
//FINISHING, CLOSING RESOURCES #1
mEnd = true;
}
}
};
TaskMgr tm;
void addTask(std::string task) {
tm.Tasks.enqueue(task);
if (tm.mEnd || !tm.mStart) boost::thread(boost::bind(&TaskMgr::run, tm)); #2
}
int main()
{
addTask("TASK1"); //OK
sleep(1);
addTask("TASK2"); //Does not create new thread, because tm.mEnd == false && tm.mStart == true
sleep(5);
addTask("TASK3"); //OK, and manager will handle both TASK2 and TASK3
sleep(15);
}
class TaskMgr{
公众:
//这是一个线程安全且无锁的队列实现
静态并发任务列表;
std::原子mRun;
std::原子mStart;
公众:
TaskMgr(){mStart=mRun=false;}
~TaskMgr(){}
无效运行(){
mStart=true;
而(!修补){
//处理队列任务
字符串任务;
while(任务。尝试退出(任务)){
//用任务做某事
}
//完成,关闭资源#1
修正=正确;
}
}
};
TaskMgr tm;
void addTask(std::string任务){
tm.Tasks.enqueue(任务);
if(tm.mEnd | | |!tm.mStart)boost::thread(boost::bind(&TaskMgr::run,tm));#2
}
int main()
{
addTask(“TASK1”);//确定
睡眠(1);
addTask(“TASK2”);//不创建新线程,因为tm.mEnd==false&&tm.mStart==true
睡眠(5);
addTask(“TASK3”);//确定,manager将同时处理TASK2和TASK3
睡眠(15);
}
因此,我有一个任务管理器,它处理string
任务<代码>任务是一种并发线程安全和无锁队列实现,它将减少锁定和同步开销。
但是,这个例子至少有一个问题:
如果#2仅在线程执行#1:colsing resources时检查mEnd
原子,mEnd
仍然是false
,mStart
是true
,因此不会创建新线程,并且只有添加了实际触发线程创建的新项后才会处理“TASK2”
我不希望线程持续运行,任务频率很低,但我也不想丢失任务,如果可能的话,尽量降低开销。实现这一点的标准方法是让任务调度器在队列为空时等待条件变量。当线程将任务推送到空队列时,它应该向条件变量发送信号。C++11添加了对这些线程原语的支持,因此您可以使用
std::condition\u variable
(当然还有std::mutex
)。当然,你可以使用Boost来代替,这是导致这些事情被采纳到C++标准中的原因。注意,既然你使用的是无锁队列,那么在推送时,你可能不知道队列是否是空的。因此,您每次都可以向条件变量发送信号。是的,您仍然有一个用于调度程序的互斥体,但是排队任务的线程都不需要处理这个问题。我将进一步注意到,由于任务频率较低,对于任何类型的无锁实现来说,进行优化似乎都是过早的。无锁功能的全部要点是用于关键应用程序(如实时音频)中的高频和低延迟任务。是的,一般来说。显然,创建线程比切换到运行线程的开销更高。这就是为什么我们通常避免在可能的情况下创建线程(最好使用线程池或类似的方法)。创建线程确实需要少量内存(对于线程的进程状态、堆栈等),但在您的情况下,线程将处于等待状态,直到发出条件变量的信号。虚假信号相对较少,因此线程几乎总是在你想要的时候才会唤醒。看起来你试图将这些不同的想法结合到一种混合方法中,但这可能不是最好的方法。实际上,您正在创建一个可以动态增长的线程池。但是您没有对线程数量设置限制。您可以考虑允许线程池增长到由可用的逻辑处理器数量决定的某个大小,但没有较大的大小。您还可以考虑允许空闲一段时间的线程退出。您可能不需要无锁队列。