首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >指定启动::异步时不执行

指定启动::异步时不执行
EN

Stack Overflow用户
提问于 2014-01-09 14:50:52
回答 2查看 3K关注 0票数 4

也许我错过了新std::async在C++11中的正确用法,但是这个语句(在cppreference.com上):

如果设置了异步标志(即policy &std::state::异步= 0),那么异步在单独的执行线程上执行函数f,就像由std::线程(f,args.)生成的那样,除非函数f返回值或抛出异常,它存储在可通过std::期货访问的共享状态中,异步返回给调用方。

使我认为我的线程应该立即以以下语句开头:

代码语言:javascript
复制
std::async(std::launch::async, MyFunctionObject());

而不必等待调用std::future::get()。情况似乎并非如此(用MSVC 13编译)。如果这不是由这个语句本身触发的,那么如果我不关心std::future对象的返回值,该如何触发呢?

示例:

代码语言:javascript
复制
#include <thread>
#include <iostream>
#include <array>
#include <future>

static std::mutex write_mutex;

class Cpp11Threads {
public:
    // Function operator for Function-Object
    void operator()() {
        const int num_threads = 50;

        // Static std array
        std::array<std::thread*, num_threads> worker_threads;

        // Range based
        for (std::thread*& thread : worker_threads) {

            // Lambda expression
            thread = new std::thread(
                [] {
                    static int i = 0;
                    write_mutex.lock();
                    std::cout << "Hello, I am happy Std thread #" << i++ << std::endl;
                    write_mutex.unlock();
                });
        }

        for (std::thread*& thread : worker_threads) {
            thread->join();
            delete thread;

            // nullptr instead of NULL
            thread = nullptr;
        }
    }
};

int main() {
    std::async(std::launch::async, Cpp11Threads());
    return 0;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-09 15:12:38

您必须知道的第一件事是,MSVC std::async不符合C++11标准。

在C++11标准下,std::asyncstd::future返回值会阻塞,直到std::async完成。

MSVC的实现没有。这使得他们的std::async看起来更容易使用,但在实践中却相当棘手。

然而,正如std::async的行为是用std::thread来描述的,我们可以看看当您启动std::thread而没有清理它时会发生什么。由此产生的std::thread实际上是被分离的。一旦您退出main,C++标准就不会指定这些std::thread发生了什么,而是留给您特定的实现。

在快速研究的基础上,当MSVC窗口程序从主程序结束时,线程被终止。

简而言之,您的程序需要与您以某种方式启动的线程重新同步,以便它们能够完成任务,并防止主程序退出main。这样做的一个简单方法是从您的std::future任务中存储返回的async,并在main退出之前在其上存储wait

如果您有一个符合标准的C++11编译器,那么您尝试的async就不会是异步的,因为它会在它返回的匿名std::future被销毁后立即阻塞。

最后,请注意,启动的thread等可能不会在创建后立即运行。他们如何和何时运行是不可预测的。

C++11并发原语仅仅是原语。他们中的许多人都有古怪的行为,比如如果std::thread在没有被detach编辑或join编辑的情况下被破坏,那么它会调用terminate;如果您不存储futureasync就会阻止它。它们可以用于简单的任务,也可以用于编写更高级别的库,但它们对用户并不友好。

票数 9
EN

Stack Overflow用户

发布于 2014-01-09 15:00:17

我不太精通C++11,但是每个程序都有一个主线程,它是执行main()函数的线程。当该线程的执行完成时,程序将与其所有线程一起完成。如果希望主线程等待其他线程,则必须使用以下内容

pthread_join

在linux环境中(如果您手动创建线程),或者完全正确

std::未来::get()

在这个特殊的情况下。

退出main会杀死您的线程,在您的情况下可能会阻止您启动线程。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21023477

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档