c++multithreadingstdthread

How does the compiler know what instructions to block when jthread::join is called?


Take this code:

#include <iostream>
#include <thread>

using namespace std::literals;

void print(std::string msg) {
    while (true) {
        std::cout << msg << '\n';
        std::this_thread::sleep_for(3s);
    }
}

int main() {
    std::jthread t1{ print, "Hello world!" };
    std::jthread t2{ print, "Batman" };

    t1.join();
    std::cout << "Is not printed\n";
    t2.join();

    return 0;
}

In this code, both t2 and t1 are executed concurrently, but "Is not printed" is never printed. If join blocks the current thread until the joined thread finishes, how is the code t2.join() ever called, since t1 should run forever? Isn't the call to t2.join() in the main thread, which should be blocked? Does the compiler have special rules that it will only block instructions that are not calls to std::jthread::join, like std::cout << "Is not printed?"?

EDIT: When I ran this program, I expected only "Hello world" to be printed every 3 seconds, but for some reason it prints Batman every 3 seconds as well. I am confused by this behavior, because I thought the program should block until t1 finished. I am aware that t1, t2, and the main thread are different threads. I know that only the main thread should be blocked, in which case "Batman" should be printed. However, the call the start t2 is in the main thread. Why isn't that instruction blocked, as opposed to std::cout << "Is not printed"?


Solution

  • When you invoke t1 and t2, on the first two lines of main(), then those threads begin executing immediately. At that moment, 3 functions are running simultaneously in 3 threads: t1, t2, and main().

    This is why you see "hello world" and "batman" both being printed. Because those threads are both executing those functions concurrently.

    Your main() function is blocked on t1.join(). This is waiting for t1 to finish executing. So your main() function never even gets to the "Is not printed" line, as it is still waiting for t1 to finish (and t1 will never finish because you have an infinite loop.)

    All join() means is "wait here until the thread is done executing."