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 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:
- Multithreading in C++0x Part 1: Starting Threads
- Multithreading in C++0x Part 2: Starting Threads with Function Objects and Arguments
- Multithreading in C++0x Part 3: Starting Threads with Member Functions and Reference Arguments
- Multithreading in C++0x Part 4: Protecting Shared Data
- Multithreading
in C++0x Part 5: Flexible locking
with
std::unique_lock<>
- Multithreading in C++0x part 6: Lazy initialization and double-checked locking with atomics
- Multithreading in C++0x part 7: Locking multiple mutexes without deadlock
- Multithreading in C++0x part 8: Futures, Promises and Asynchronous Function Calls
Posted by Anthony Williams
[/ threading /] permanent link
Tags: concurrency, multithreading, C++0x, thread
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Design and Content Copyright © 2005-2024 Just Software Solutions Ltd. All rights reserved. | Privacy Policy
13 Comments
Very good tutorial. I have found one more reference for multithreading at https://www.tutorialcup.com/cplusplus/multithreading.htm
Install Windows8 ISO on Virtualbox and start with C++11 immediatly. Lots of fun!
hey buddy!
good job, is a nice paper!!
[]s
Nice introduction! I am excited to learn more about std::thread&Co. Do you know what can I use until C++0x emerges? Thanks!
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.A few more concise articles like this and I will feel confident enough to make thread programming a part of my daily routine. Thanks
I can't believe you expect people to pay for your std:thread implementation.
> 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
I get a segmentation fault.... (and even after setting ulimit to unlimited) i am still not getting a core :(
any clues ?
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.
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.
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
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.