如何使生成的线程拖延足够长的时间以使生成线程执行某些操作



另一个SO线程解释了如何使用thread::native_handle来执行C++线程API之外的事情(例如,设置线程的优先级)。要点是:

std::thread t(functionToRun);
auto nh = t.native_handle());
// configure t using nh           

这种方法的问题在于,在配置 t 的代码完成之前,functionToRun可能会执行任意时间(包括完成)。

我相信我们可以通过以下方式防止这种情况发生(未经测试):

std::atomic<bool> configured(false);
std::thread t([&]{ while (!configured);   // spin until configured is true
                   functionToRun(); });
auto nh = t.native_handle();
// configure t using nh
configured = true;

不幸的是,这会导致生成的线程旋转,等待configured变为真。在配置完成之前,最好阻止生成的线程。

实现这一点的一种方法似乎是使用互斥锁(也未经测试):

std::mutex m;
std::unique_lock<std::mutex> lock(m);
std::thread t([&]{ std::lock_guard<std::mutex> lg(m);   // block until m available
                   functionToRun(); });
auto nh = t.native_handle();
// configure t using nh
lock.unlock();                                          // allow t to continue

这似乎应该有效,但是从概念上讲,condvar似乎更适合指示何时满足条件(配置完成)的工作。 但是使用 condvar 需要上述所有内容,再加上一个 condvar,并且需要处理杂散唤醒的可能性,据我所知,这对互斥体来说不是问题。

有没有更好的方法来生成一个线程,然后让它立即停止,以便我可以在允许它进一步运行之前使用它的本机句柄来配置它?

当我希望延迟线程主函数的启动直到完成某些外部配置时,我使用 future。这避免了自旋等待,并且具有与互斥锁或 condvar 相同的阻塞属性,但提供了更明确的意图。使用此模式,您可以将示例编写为:

std::promise<void> p;
std::thread t([&p]{
    p.get_future().wait();
    thread_func();
}
auto nh=t.native_handle();
// configure nh
p.set_value();

我特别喜欢将此模式与多线程测试的shared_future一起使用---这样您就可以确保所有线程都在运行并在测试开始之前准备就绪。

最新更新