我目前在我的线程池中有一个带有x worker 的程序.在主循环Ÿ任务分配给工人来完成,但之后的任务被发送出去,我必须与节目之前之前等待所有任务完成.我相信我目前的解决方案效率低下,必须有更好的方法等待所有任务完成,但我不知道如何去解决这个问题
// called in main after all tasks are enqueued to
// std::deque<std::function<void()>> tasks
void ThreadPool::waitFinished()
{
while(!tasks.empty()) //check if there are any tasks in queue waiting to be picked up
{
//do literally nothing
}
}
Run Code Online (Sandbox Code Playgroud)
更多信息:
线程池结构
//worker thread objects
class Worker {
public:
Worker(ThreadPool& s): pool(s) {}
void operator()();
private:
ThreadPool &pool;
};
//thread pool
class ThreadPool {
public:
ThreadPool(size_t);
template<class F>
void enqueue(F f);
void waitFinished();
~ThreadPool();
private:
friend class Worker; …Run Code Online (Sandbox Code Playgroud) 我有一些代码std::thread从C++ 11 <thread>标头动态分配一个新的代码,如下所示:
std::thread *th = new thread( /* my args */);
Run Code Online (Sandbox Code Playgroud)
一段时间后,我打电话给加入:
th->join();
Run Code Online (Sandbox Code Playgroud)
由于我动态分配了线程,我是否还需要调用delete th;以释放内存?如果我这样做,我还需要先打个电话join()吗?
这个问题与前一个问题非常类似:pthread_once()中的竞争条件?
它本质上是同一个问题 - std::promise在调用期间结束 的生命周期promise::set_value(即:在关联的未来被标记之后但在pthread_once执行之前)
所以我知道我的用法有这个问题,因此我不能以这种方式使用它.但是,我认为这是不明显的.(用Scott Meyer明智的话说:使接口易于正确使用且难以正确使用)
我在下面提供一个范例:
dispatcher),它在队列中旋转,弹出一个'job'(a std::function)并执行它.synchronous_job,它会阻塞调用线程,直到在调度程序线程上执行'job'std::promise和std::future是的成员synchronous_job-一旦future被设置,呼叫阻止线程继续,这导致synchronous_job从堆栈弹出和被破坏.dispatcher在内部 切换了上下文promise::set_value; 在future被标记,但呼叫pthread_once尚未执行,并且并行线程堆栈以某种方式损坏,这意味着在明年的时间:死锁 我希望召唤promise::set_value是原子的; 事实上,在标记了future遗嘱之后需要做更多工作这一事实在以这种方式使用这些类时会不可避免地导致这种问题.
所以我的问题是:如何使用std::promise和实现这种同步,并将std::future它们的生命周期与提供此同步机制的类相关联?
@Jonathan Wakely,你是否可以condition_variable在内部使用一些RAII风格的类,它在标记之后设置它的析构函数future?这意味着即使promise在调用中被破坏set_value,设置条件变量的额外工作也会正确完成.只是一个想法,不确定你是否可以使用它...
下面是一个完整的工作示例,以及之后的死锁应用程序的堆栈跟踪:
#include <iostream>
#include <thread>
#include <future>
#include <queue>
struct dispatcher …Run Code Online (Sandbox Code Playgroud) 考虑我的测试代码:
#include <thread>
class Foo {
public:
void threadFunc() {}
void startThread() {
_th = std::thread(&Foo::threadFunc, *this);
}
private:
std::thread _th;
};
int main(int argc, char *argv[])
{
Foo f;
f.startThread();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是它产生的错误:
../untitled/main.cpp:13:14: warning: unused parameter 'argc' [-Wunused-parameter]
int main(int argc, char *argv[])
^
../untitled/main.cpp:13:26: warning: unused parameter 'argv' [-Wunused-parameter]
int main(int argc, char *argv[])
^
In file included from ../untitled/main.cpp:1:
In file included from /usr/bin/../lib/c++/v1/thread:90:
In file included from /usr/bin/../lib/c++/v1/__functional_base:15:
/usr/bin/../lib/c++/v1/type_traits:1372:12: error: call to implicitly-deleted copy …Run Code Online (Sandbox Code Playgroud) 假设我有一个工作线程tWorker,它在Boss构造时被初始化并告诉它要做work(),直到bRetired为真.An std::mutex,mtx锁定一些data(vFiles),以便tWorker在他处理它时拥有它.
怎样使tWorker"自杀"一度bRetired成为true?mutex当线程停止执行时如何销毁?
我已经读过,std::thread对象不能以任何方式中断.让线程什么也不做(或调用std::this_thread::yield())提供与杀死线程相同的效果?
class Boss {
private:
std::thread tWorker;
std::mutex mtx;
bool bRetired;
std::vector< std::string > vFiles;
void work() {
while ( bRetired == false ) {
// Do your job!
mtx.lock();
// ... Do something about vFiles ...
mtx.unlock();
}
// tWorker has retired, commit suicide
// ** How? **
// …Run Code Online (Sandbox Code Playgroud) 我正在阅读C++ Concurrency in Action一书,以了解有关线程和C++内存模块的更多信息.我很好奇在以下代码中调用复制构造函数的次数:
struct func
{
func() = default;
func(const func& _f) {}
void operator()() {}
};
int main()
{
func f;
std::thread t{ f };
t.join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我在Visual Studio 2013调试器中浏览此代码时,我看到复制构造函数分别被调用了四次.它从主线程调用三次,然后从新线程调用一次.我期待一个,因为它为新线程制作了一个对象的副本.为什么要创建三个额外副本?
c++ multithreading copy-constructor stdthread visual-studio-2013
考虑以下简短程序:
#include <thread>
int Foo() {
while (1);
}
int main(){
std::thread t(Foo);
std::thread s(Foo);
// (std::thread(Foo));
t.join();
}
Run Code Online (Sandbox Code Playgroud)
这编译和运行(永远),与
g++ -Wl,--no-as-needed DoubleBufferTest.cc -o DoubleBufferTest -std=c++0x -pthread
Run Code Online (Sandbox Code Playgroud)
在注释掉的行中,我试图使用此处描述的技术匿名声明一个新线程.但是,当该行被注释回来时,我可以编译但运行时会出现以下错误:
terminate called without an active exception
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)
我怎样才能正确地匿名声明一个帖子?
请注意,我在g++ 4.4.7.
我正在构建一个实时软件,我有一个主要的无限循环main()和用于读取和处理数据的线程.
其中一个问题是保持一个std::vector正在运行的线程向它们发送信号并监视执行.所以我把这段代码放在一起:
#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <chrono>
namespace readerThread {
void start(int id)
{
while (1)
{
std::cout << "Reader " << id << " running..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
}
int main()
{
int readers[] = { 1, 2, 3 };
std::vector<std::thread> readerThreads;
for (int &reader : readers)
{
std::thread th(readerThread::start, reader);
readerThreads.push_back(th);
}
while(true)
{
std::cout << "Waiting..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它甚至没有编译,得到这个错误:
In file …Run Code Online (Sandbox Code Playgroud) 为了更好地理解这个问题,代码如下:
// code 1
#include <iostream>
#include <thread>
struct tls_test {
tls_test()
{ std::cout << "tls_test ctor\n"; }
~tls_test()
{ std::cout << "tls_test dtor\n"; }
void print() const
{ std::cout << "tls_test print\n"; }
};
thread_local tls_test t;
void thread_1()
{
std::cout << "thread_1 started\n";
t.print();
std::cout << "thread_1 return\n";
}
int main()
{
std::thread trd{ thread_1 };
trd.join();
std::cout << "main return\n";
}
Run Code Online (Sandbox Code Playgroud)
我正在使用 TDM-GCC 和 Windows 10 来测试该程序。这是输出:
// code 1
#include <iostream>
#include <thread>
struct tls_test { …Run Code Online (Sandbox Code Playgroud) 我有以下代码,我认为它可以正常工作(请原谅愚蠢/人为的例子)。
void run_thread()
{
std::thread t([]{
while(true)
{
// keep getting chars... to stop peoples eye's hurting : )
char c = getchar();
}
});
t.detach(); // Detach thread
// thread goes out of scope here - but is it ok because its detached??
}
int main()
{
run_thread();
// Wait here forever
while (true) {;}
}
Run Code Online (Sandbox Code Playgroud)
但在重读之后,我对它产生了怀疑。线程 t 超出范围。我现在不记得在你调用 detach() 之后这样做是否安全......我想是的,但正如我所说,我有一个唠叨的疑问。任何人都可以确认这是否是好的/坏的做法?