2

I'm new to threads in C++ 11. I have two threads and I want to make them start at the exact same time. I could think of two ways of doing it (as below). However, it seems that none of them work as I expected. They are start one thread before launching another. Any hint would be appreciated! Another question is I'm working on a threaded queue. So I would have two consumers and four producers. Is the following code for consumer the right way to go? Is there any reference that anyone can provide?

for(int i = 1; i <= 2; i++)
    auto c = async(launch::async, consumer, i);


auto c1 = async(launch::async, consumer, 1);
auto c2 = async(launch::async, consumer, 2);
2
  • 3
    There's no such thing as "time". A sequential ordering of events across multiple, concurrent execution contexts can only be defined in terms of observable events, i.e. synchronization points. Commented May 19, 2014 at 0:20
  • 1
    Note that even if two threads start running "at the same time", it's entirely possible for one of them to run to completion before the other one gets to execute its second instruction. So the exact time when a thread starts is basically irrelevant. You should think in terms of synchronizing the interactions between threads. Commented May 19, 2014 at 2:53

3 Answers 3

3

What the other answers said about it not being possible to guarantee that two threads start at the same time is true. Still, if you want to come close there are different ways to do that.

One way is to use a set of std::promises to indicate when everything is ready. Each thread sets a promise to indicate that it's ready and then waits on a (copy of a) std::shared_future obtained from a third std::promise; the main thread waits for all the promises from all the threads to be set and then triggers the threads to go. This ensures that each thread has started and is just before the chunk of code that should be run concurrently.

std::promise<void> go, ready1, ready2; // Promises for ready and go signals
std::shared_future<void> ready(go.get_future()); // Get future for the go signal
std::future<void> done1, done2; // Get futures to indicate that threads have finished
try
{
    done1 = std::async(std::launch::async, 
        [ready, &ready1]
    {
        ready1.set_value(); // Set this thread's ready signal
        ready.wait(); // Wait for ready signal from main thread
        consumer(1);
    });
    done2 = std::async(std::launch::async,
        [ready, &ready2]
    {
        ready2.set_value(); // Set this thread's ready signal
        ready.wait(); // Wait for ready signal from main thread
        consumer(2);
    });
    // Wait for threads to ready up
    ready1.get_future().wait();
    ready2.get_future().wait();
    // Signal threads to begin the real work
    go.set_value();
    // Wait for threads to finish
    done1.get();
    done2.get();
}
catch (...)
{
    go.set_value(); // Avoid chance of dangling thread
    throw;
}

Note: most of this answer was copied from "C++ Concurrency in Action" by Anthony Williams (pages 311-312), but I adapted the code to fit the example in the question.

Sign up to request clarification or add additional context in comments.

Comments

1

to launch two threads simultaneously I see no other way than first launching 2 threads the classic way, then blocking them using a barrier to synchronize them, but the release broadcast has no guarantee of re-scheduling them both at the same time. Alternatively you could spin check a global time counter or something but even then...

1 Comment

Actually I found that the above two way of creating thread have different results. The second way seems to get closer to running at the same time.
0

It is impossible to start two threads at one time. The CPU can only do one thing at a time. It threads by stopping one thread, saving register states, and restoring those of the other thread, and executing that thread for a while. Think of it more like this (though not exactly how it works).

hey cpu, i want to do two things at once, eat apples and bananas

CPU says

ok, well, heres what we will do. Eat a bit of an apple
now, eat some banana
repeat..

Therefore, you can start them in close proximity, but not at the exact same time.

3 Comments

This was true back when a computer only had one CPU/core. In nearly any modern CPU it's false though. Virtually all modern CPUs have at least two cores, so they can and do execute at least two threads simultaneously.
correct, note that I stated (not exactly). A good process scheduler can execute on multiple cores at the same "time", but it depends on the operating system. A good rule of thumb is to assume that they are not, and to correct for that via resource locking and CPU waits.
Also, sorry if I am still "in the stone age" but everything I use is generally single core ARM CPUs

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.