Multithreading in C++0x part 1: Starting Threads

Tuesday, 10 February 2009

This is the first of a series of blog posts introducing the new C++0x thread library.

Concurrency and multithreading is all about running multiple pieces of code in parallel. If you have the hardware for it in the form of a nice shiny multi-core CPU or a multi-processor system then this code can run truly in parallel, otherwise it is interleaved by the operating system — a bit of one task, then a bit of another. This is all very well, but somehow you have to specify what code to run on all these threads.

High level constructs such as the parallel algorithms in Intel's Threading Building Blocks manage the division of code between threads for you, but we don't have any of these in C++0x. Instead, we have to manage the threads ourselves. The tool for this is std::thread.

Running a simple function on another thread

Let's start by running a simple function on another thread, which we do by constructing a new std::thread object, and passing in the function to the constructor. std::thread lives in the <thread> header, so we'd better include that first.

#include <thread>

void my_thread_func()
{}

int main()
{
    std::thread t(my_thread_func);
}

If you compile and run this little app, it won't do a lot: though it starts a new thread, the thread function is empty. Let's make it do something, such as print "hello":

#include <thread>
#include <iostream>

void my_thread_func()
{
    std::cout<<"hello"<<std::endl;
}

int main()
{
    std::thread t(my_thread_func);
}

If you compile and run this little application, what happens? Does it print hello like we wanted? Well, actually there's no telling. It might do or it might not. I ran this simple application several times on my machine, and the output was unreliable: sometimes it output "hello", with a newline; sometimes it output "hello" without a newline, and sometimes it didn't output anything. What's up with that? Surely a simple app like this ought to behave predictably?

Waiting for threads to finish

Well, actually, no, this app does not have predictable behaviour. The problem is we're not waiting for our thread to finish. When the execution reaches the end of main() the program is terminated, whatever the other threads are doing. Since thread scheduling is unpredictable, we cannot know how far the other thread has got. It might have finished, it might have output the "hello", but not processed the std::endl yet, or it might not have even started. In any case it will be abruptly stopped as the application exits.

If we want to reliably print our message, we have to ensure that our thread has finished. We do that by joining with the thread by calling the join() member function of our thread object:

#include <thread>
#include <iostream>

void my_thread_func()
{
    std::cout<<"hello"<<std::endl;
}

int main()
{
    std::thread t(my_thread_func);
    t.join();
}

Now, main() will wait for the thread to finish before exiting, and the code will output "hello" followed by a newline every time. This highlights a general point: if you want a thread to have finished by a certain point in your code you have to wait for it. As well as ensuring that threads have finished by the time the program exits, this is also important if a thread has access to local variables: we want the thread to have finished before the local variables go out of scope.

Next Time

In this article we've looked at running simple functions on a separate thread, and waiting for the thread to finish. However, when you start a thread you aren't just limited to simple functions with no arguments: in the second part of this series we will look at how to start a thread with function objects, and how to pass arguments to the thread.

Subscribe to the RSS feed RSS feed or email newsletter for this blog to be sure you don't miss the rest of the series.

Try it out

If you're using Microsoft Visual Studio 2008 or g++ 4.3 or 4.4 on Ubuntu Linux you can try out the examples from this series using our just::thread implementation of the new C++0x thread library. Get your copy today.

Multithreading in C++0x Series

Here are the posts in this series so far:

Posted by Anthony Williams
[/ threading /] permanent link
Tags: , , ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the right.

12 Comments

Nice introduction! I am excited to learn more about std::thread&Co. Do you know what can I use until C++0x emerges? Thanks!

by Zdravko at 07:36:08 on Thursday, 12 February 2009

If you're using Microsoft Visual Studio 2008, you can use my just::thread implementation of the C++0x library --- http://www.stdthread.co.uk

A linux version is in the pipeline.
by Anthony Williams at 08:23:45 on Thursday, 12 February 2009

A few more concise articles like this and I will feel confident enough to make thread programming a part of my daily routine. Thanks

by Ganeshram Iyer at 21:48:12 on Thursday, 12 February 2009

I can't believe you expect people to pay for your std:thread implementation.

by Filbert Cray at 22:53:05 on Wednesday, 01 July 2009

hey buddy!

good job, is a nice paper!!

[]s

by Jorge Pereira at 22:15:01 on Friday, 31 July 2009

> Well, actually, no, this app does not have predictable behaviour. The problem is we're not waiting for our thread to finish. When the execution reaches the end of main() the program is terminated, whatever the other threads are doing. Since thread scheduling is unpredictable, we cannot know how far the other thread has got. It might have finished, it might have output the "hello", but not processed the std::endl yet, or it might not have even started. In any case it will be abruptly stopped as the application exits.

Hi Anthony, could you please clarify this thing? If I leave any threads running and then finish my main() function (or call std::exit()) - is it a correct program? Will its behavior be defined or undefined or unspecified?

I failed to find a clear answer in the latest draft.

Also, what do these words from the draft mean: "Terminating every thread before a call to std::exit or the exit from main is sufficient, but not necessary, to satisfy these requirements. These requirements permit thread managers as static-storage-duration objects."?

Thanks, Maxim

by Maxim Yanchenko at 05:58:39 on Friday, 11 September 2009

I get a segmentation fault.... (and even after setting ulimit to unlimited) i am still not getting a core :(

any clues ?

by Moh at 07:54:44 on Sunday, 07 February 2010

Hi Moh,

By your reference to ulimit and core dumps, I'm guessing you're using gcc on linux. In this case you need to ensure that you're using the -pthread option to gcc:

g++ -pthread -std=c++0x file.cpp

If you're using just::thread, you'll also need to ensure that you set the include path correctly, and link against the library.

by Anthony Williams at 21:13:39 on Monday, 08 February 2010

Hi Maxim,

You *can* leave a thread running and return from main or call std::exit. That in itself doesn't lead to an incorrect program. However, if you do so then you need to ensure that the threads left running do not use any objects of static storage duration that have already been destroyed. If you never use any such objects anyway then you're already safe.

As the comment in the working draft says, you can have a static object that joins with a thread in its destructor, but the thread had better not touch any static objects that have already been destroyed.

by Anthony Williams at 21:22:42 on Monday, 08 February 2010

Hi all, I start playing with Microsoft Visual Studio 2010 C++. Where is the file <thread> ?

Without it, I can't compile the example from this page.

Thanks a lot in advance, Arkady Tunik

My version details: Version 10.0.20506.1 Beta1 Microsoft .NET Framework Version 4.0 Installed Version: Professional Microsoft Silverlight Projects 2010 91605-005-5610054-60134 Microsoft Silverlight Projects 2010 Version 10.0.20506.1 Microsoft Visual Basic 2010 91605-005-5610054-60134 Microsoft Visual Basic 2010 Microsoft Visual C# 2010 91605-005-5610054-60134 Microsoft Visual C# 2010 Microsoft Visual C++ 2010 91605-005-5610054-60134 Microsoft Visual C++ 2010 Microsoft Visual F# 2010 91605-005-5610054-60134 Microsoft Visual F# 2010 Microsoft Visual Studio 2010 Tools for the Microsoft Office system 91605-005-5610054-60134 Microsoft Visual Studio 2010 Tools for the Microsoft Office system Microsoft Visual Web Developer 2010 91605-005-5610054-60134 Microsoft Visual Web Developer 2010 Workflow Designer Package 1.0 Package for WPF based Microsoft Workflow Designer

by Arkady Tunik at 10:24:51 on Saturday, 20 February 2010

Hi Arkady,

VS2010 doesn't provide any of the C++0x thread library headers. You can use the C++0x thread library with VS2008 (including the express version) by purchasing my just::thread library from http://www.stdthread.co.uk/order.html There's a 30-day money back guarantee, so you can try it absolutely risk free. V1.3.1 doesn't support VS2010, but the next release will, and you'll get a free upgrade if you buy now.

by Anthony Williams at 21:20:38 on Sunday, 21 February 2010

Install Windows8 ISO on Virtualbox and start with C++11 immediatly. Lots of fun!

by Volker Roth at 10:27:02 on Saturday, 29 October 2011

Add your comment

Your name:

Your URL:

Email address:

Person or spambot?

Your comment: