C++处理主线程中的多线程
我对多线程有点新,所以请原谅我,如果这些问题太微不足道了。C++处理主线程中的多线程
我的应用程序需要在线程中创建多个线程并从每个线程执行操作。
例如,我有一组要读取的文件,比如说50,我创建了一个使用CreateThread()函数读取这些文件的线程。
现在这个主线程创建4个线程来访问文件。第一个线程给出文件1,第二个文件2等等。
第一个线程完成读取文件1并给主线程所需的数据后,主线程需要用文件5调用它并从中获取数据。所有其他线程的情况类似,直到读取所有50个文件。
之后,每个线程被销毁,最后我的主线程被销毁。
我现在面临的问题是:
1)如何停止一个线程文件读取后退出?
2)如何用其他文件名再次调用线程?
3)我的子线程如何给主线程提供信息?
4)线程完成读取文件并返回主线程数据后,主线程将知道哪个线程提供了数据?
谢谢
这是一个在多线程编程中很常见的问题。您可以将其视为生产者 - 消费者问题:主线程“生成”由工作线程“消耗”的任务(例如,例如http://www.mario-konrad.ch/blog/programming/multithread/tutorial-06.html)。您可能还想阅读“线程池”。
我强烈建议读入boost的同步(http://www.boost.org/doc/libs/1_50_0/doc/html/thread.html)并使用boost的线程功能,因为它是独立于平台并且很好用的。
更具体到你的问题:你应该创建一个带有操作的队列(通常它对于所有工作线程是相同的队列,如果你确实想确保线程1正在执行任务1,5,9。 ..你可能希望每个工作者线程有一个队列)。访问此队列必须同步mutex
,等待线程可以通过condition_variables
通知,当新数据添加到互斥锁时。
1)不退出线程的功能,但等到条件被触发,然后重新启动使用while ([exit condition not true])
循环
2)请参见第1
3)通过任何变量,其都有权访问并且受到mutex
(例如结果队列)的保护
4.)通过添加此信息作为写入结果队列的结果。
另一个建议:多线程正确性总是很困难。因此,尽可能小心并编写测试来检测死锁和竞争条件。
这种问题的典型解决方案是使用线程池和队列。主线程将所有文件/文件名推送到一个队列中,然后启动一个线程池,即不同的线程,其中每个线程从队列中取一个项目并处理它。当一个项目被处理时,它会继续到下一个项目(如果到那时队列还没有被清空)。主线程知道在队列为空并且所有线程都退出时处理所有内容。
因此,1)和2)有些冲突:您不会停止线程并再次调用它,只要它在队列中找到项目,它就会继续运行。 对于3)可以再次使用线程放入信息并从中读取主线程的队列。对于4)你可以给每个线程一个id并把它和数据放在一起。但是,通常主线程不需要知道哪个线程正确处理了数据。
一些非常基本的伪代码,给你一个想法,锁定为threadsafety省略:
//main
for(all filenames)
queue.push_back(filename);
//start some thread
threadPool.StartThreads(4, CreateThread(queue));
//wait for threads to end
threadPool.Join();
//thread
class Thread
{
public:
Thread(queue q) : q(q) {}
void Start();
bool Join();
void ThreadFun()
{
auto nextQueueItem = q.pop_back();
if(!nextQueuItem)
return; //q empty
ProcessItem(nextQueueItem);
}
}
无论是使用线程池或不执行你的synchronies文件读取,把它归结为功能或链条必须运行序列化的函数组。因此,让我们假设,您可以找到一种并行执行函数的方法(无论是为每个函数启动一个线程还是通过使用线程池),等待前4个文件读取,您可以使用队列,读取线程将结果推入,第五个函数现在将4个结果从队列中取出(队列块为空时)和进程。如果函数之间存在更多依赖关系,则可以在它们之间添加更多队列。素描:
void read_file(const std::string& name, queue& q)
{
file_content f= .... // read file
q.push(f)
}
void process4files(queue& q)
{
std::vector<file_content> result;
for (int i = 0; i != 4; ++i)
result.push_back(q.pop());
// now 4 files are read ...
assert(result.size() == 4u);
}
queue q;
thread t1(&read_file, "file1", q);
thread t2(&read_file, "file2", q);
thread t3(&read_file, "file3", q);
thread t4(&read_file, "file4", q);
thread t5(&process4files, q);
t5.join();
我希望你明白了。
Torsten
是'队列'的'std :: queue'吗?那么你的例子就是缺少互斥或其他锁定机制,对吧? – Philipp 2012-07-23 06:52:08
这就是为什么它说'锁定螺纹省略':] – stijn 2012-07-23 07:27:34
哎呀,对不起:-) – Philipp 2012-07-23 07:58:35