Initializing global object from one thread and waiting for it in other threads
Seems reasonable to me. Just a few nits first:


You should never using namespace std; in real code. Just write std::string, and so on. It'll save your readers some confusion, and it'll avoid subtle bugs related to ADL that you'll only learn about much later in life.
using namespace std::chrono_literals is presumably a type for using namespace std::literals or maybe using namespace std::literals::chrono_literals.
You've got some spurious semicolons: }; should be } in at least one place.




Unless the value of the bool being passed through the future — true or false — is meaningful, it shouldn't be part of your program. In this case you could (and therefore should) be using std::shared_future&lt;void&gt; instead of std::shared_future&lt;bool&gt;.



There is a simpler and therefore perhaps better thread-synchronization mechanism, if all your threads are launching from the same spot at the same time. Use a mutex which is locked when the threads spawn, and force each thread to "check in" by locking that mutex before it's allowed to continue. For example:

// global A object which threads of type B want to use
std::unique_ptr&lt;A&gt; gA;

void initA(std::unique_lock&lt;std::mutex&gt; lk)
{ 
    // do setup here

    gA = std::make_unique&lt;A&gt;();

    // now signal that it's okay for the B threads to start
    lk.unlock();
}

void funB(std::string name, std::mutex&amp; checkpoint)
{
    // do initial setup here

    checkpoint.lock(); checkpoint.unlock();

    gA-&gt;talk(name);
}

int main() {
    std::mutex checkpoint;
    std::unique_lock&lt;std::mutex&gt; lk(checkpoint);
    auto tB1 = std::thread(funB, string("B1"), std::ref(checkpoint));
    auto tB2 = std::thread(funB, string("B2"), std::ref(checkpoint));
    auto tB3 = std::thread(funB, string("B3"), std::ref(checkpoint));
    initA(std::move(lk));
[...]


Notice that the lk.unlock() in initA isn't strictly needed, as written, because the destructor of lk was going to drop that lock anyway. But you could put more code after lk.unlock() if you had more things to do that didn't affect gA.



Also notice that I'm using make_unique instead of reset(new ...). Always prefer to use make_unique and make_shared instead of raw new and delete — again because it helps avoid subtle exception-related bugs which if you're lucky you'll never see in the wild; but also because if you get in the habit of never writing new or delete yourself, you'll be able to spot more easily when other people's code incorrectly uses new or delete. Ideally, you want to get in a situation where you can install a git commit hook that does a git grep \bnew\b and fails if it finds any!