390

Can someone post a simple example of starting two (Object Oriented) threads in C++.

I'm looking for actual C++ thread objects that I can extend run methods on (or something similar) as opposed to calling a C-style thread library.

I left out any OS specific requests in the hopes that whoever replied would reply with cross platform libraries to use. I'm just making that explicit now.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Zak
  • 24,947
  • 11
  • 38
  • 68
  • 6
    [This question is being discussed on meta](https://meta.stackoverflow.com/q/388475/6296561) – Zoe Aug 13 '19 at 12:46

7 Answers7

701

Create a function that you want the thread to execute, for example:

void task1(std::string msg)
{
    std::cout << "task1 says: " << msg;
}

Now create the thread object that will ultimately invoke the function above like so:

std::thread t1(task1, "Hello");

(You need to #include <thread> to access the std::thread class.)

The constructor's first argument is the function the thread will execute, followed by the function's parameters. The thread is automatically started upon construction.

If later on you want to wait for the thread to be done executing the function, call:

t1.join();

(Joining means that the thread who invoked the new thread will wait for the new thread to finish execution, before it will continue its own execution.)


The Code

#include <string>
#include <iostream>
#include <thread>

using namespace std;

// The function we want to execute on the new thread.
void task1(string msg)
{
    cout << "task1 says: " << msg;
}

int main()
{
    // Constructs the new thread and runs it. Does not block execution.
    thread t1(task1, "Hello");

    // Do other things...

    // Makes the main thread wait for the new thread to finish execution, therefore blocks its own execution.
    t1.join();
}

More information about std::thread here

  • On GCC, compile with -std=c++0x -pthread.
  • This should work for any operating-system, granted your compiler supports this (C++11) feature.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MasterMastic
  • 20,711
  • 12
  • 68
  • 90
  • @user2568508 Being in the standard library, it should be, yes. Although you *will* have to acquire a compiler with this support. – MasterMastic Sep 20 '13 at 12:27
  • @Ken: I am not sure what you mean to acquire a compiler with this support... Some compilers don't have it? –  Sep 20 '13 at 12:39
  • @user2568508 Indeed. this is a C++0x (C++11) feature. I don't think a compiler that supports all of C++0x features exists yet but they have partial support and this is a common feature for them to have. – MasterMastic Sep 20 '13 at 12:51
  • Please, help, it says "cannot open include file: 'thread': no such file or directory ". I'm using VS10 on Win7. – Preza8 Oct 24 '13 at 18:22
  • @Preza8 I have not tried this with VS10, but can you add other standard headers? if yes, you should check if your MSVC++ version supports this. – MasterMastic Oct 25 '13 at 20:57
  • 5
    @Preza8 VS10 does not support many features in C++11. VS12 and VS13 support thread. – jodag Jan 09 '14 at 00:53
  • 4
    In the comment "GCC versions below 4.7, use `-std=c++0x` (instead of `-std=c++0x`)" I believe the second "c++0x" should instead be "c++11", but that's not possible to change because the edit is too small. – zentrunix Mar 25 '14 at 16:19
  • 1
    @MasterMastic What difference does it make if instead of std::thread t1(task1, "Hello") we use std::thread t1(&task1, "Hello"), passing the reference of the function? Should we declare the function as a pointer in this case? – user2452253 Nov 04 '14 at 16:32
  • 3
    @user2452253 If you pass "task1" you pass a pointer to the function you want to execute (which is good). If you pass "&task1" you pass a pointer to a pointer of a function, and the results would probably not be so pretty and very undefined (it would be like trying to execute random instructions one after another. With the right probability you *just might* open the gateway to hell). You really just want to pass the function pointer (a pointer with the value of the address where the function begins). If that doesn't clear things up, let me know, and best of luck! – MasterMastic Nov 04 '14 at 16:47
  • I still needed `-pthread` to compile it with 4.7.1, otherwise the proramm fails to run with "terminate called after throwing an instance of 'std::system_error' what(): Operation not permitted". – BeniBela Feb 18 '15 at 13:32
  • How would I do if I want the function to take the thread it is called from as parameter? – Erik W Mar 15 '15 at 19:31
  • 1
    @ErikW In the calling thread you can call [`std::this_thread::get_id()`](http://en.cppreference.com/w/cpp/thread/get_id), to get your [`std::thread::id`](http://en.cppreference.com/w/cpp/thread/thread/id); then you just pass it regularly (i.e. as I passed the `string` in the answer). – MasterMastic Mar 16 '15 at 09:05
  • I believe there is a typo, thread t1(task1, "Hello"); should be thread t1(&task1, "Hello"); – Mich Jul 07 '15 at 00:05
  • @MasterMastic should task1 be void?? I have a function that returns a value. what should I do?? – Fatemeh Karimi Jan 12 '18 at 14:32
  • 1
    @MasterMastic "_you pass a pointer to a pointer of a function_" Which pointer to function? – curiousguy Jul 05 '18 at 08:08
  • 1
    @FatemehKarimi sorry for responding so late. Generally, you should use a different construct than a thread, and I'm talking specifically about a future/promise. I'm sure you can find plenty of implementations, as well the ones in the standard library. If you need more sophistication then you'd probably look for an appropriate (i.e. thread-safe) mechanism or container for passing data, such as a queue. – MasterMastic Jul 05 '18 at 09:16
  • 2
    @curiousguy Well, the right way to do it is to pass a pointer of the function you want to run. In this case the function is `task1`. So the function pointer is also denoted by `task1`. But thank you for bringing this up because I believe I was wrong and it's equivalent to `&task1`, so it doesn't matter which form you choose to write (if so, I guess that pointer to pointer of the function is `&&task1` -- _that_ would be bad). [Relevant Question](https://stackoverflow.com/q/16917043/825637). – MasterMastic Jul 05 '18 at 09:22
  • @MasterMastic That would be `and task1` – curiousguy Jul 05 '18 at 12:17
  • Something to add here, is that if you don't want to `join` the thread, you probably want to `detach` - https://stackoverflow.com/questions/25559918/c-stdthread-crashes-upon-execution – gosukiwi Jun 29 '20 at 19:33
85

Well, technically any such object will wind up being built over a C-style thread library because C++ only just specified a stock std::thread model in C++0x, which was just nailed down and hasn't yet been implemented.

The problem is somewhat systemic. Technically the existing C++ memory model isn't strict enough to allow for well-defined semantics for all of the 'happens before' cases. Hans Boehm wrote an paper on the topic a while back and was instrumental in hammering out the C++0x standard on the topic.

Threads Cannot be Implemented as a Library

That said, there are several cross-platform thread C++ libraries that work just fine in practice. The Intel thread building blocks contains a tbb::thread object that closely approximates the C++0x standard and Boost has a boost::thread library that does the same.

Using boost::thread, you'd get something like:

#include <boost/thread.hpp>

void task1() {
    // do stuff
}

void task2() {
    // do stuff
}

int main (int argc, char ** argv) {
    using namespace boost;
    thread thread_1 = thread(task1);
    thread thread_2 = thread(task2);

    // do other stuff
    thread_2.join();
    thread_1.join();
    return 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Edward Kmett
  • 29,632
  • 7
  • 85
  • 107
  • 10
    Boost thread is great - my only problem was that you couldn't (when I last used it) actually access the native underlying thread handle as it was a private class member! There's a TON of stuff in win32 that you need the threadhandle for, so we tweaked it to make the handle public. – Orion Edwards Nov 05 '08 at 19:40
  • 5
    Another problem with boost::thread is that as I recall you don't have the freedom to set the stack size of the new thread -- a feature that is also lamentably not included in c++0x standard. – Edward Kmett Nov 05 '08 at 20:13
  • That code gives me a boost::noncopyable exception for this line: thread thread_1 = thread(task1); Maybe it's because I'm using an older version (1.32). – Frank Feb 21 '09 at 00:42
  • task1 was not declared in this scope? – Jake Gaston Mar 22 '19 at 20:45
30
#include <thread>
#include <iostream>
#include <vector>
using namespace std;

void doSomething(int id) {
    cout << id << "\n";
}

/**
 * Spawns n threads
 */
void spawnThreads(int n)
{
    std::vector<thread> threads(n);
    // spawn n threads:
    for (int i = 0; i < n; i++) {
        threads[i] = thread(doSomething, i + 1);
    }

    for (auto& th : threads) {
        th.join();
    }
}

int main()
{
    spawnThreads(10);
}
Damian
  • 4,395
  • 4
  • 39
  • 67
Caner
  • 57,267
  • 35
  • 174
  • 180
  • 2
    An explanation would be in order. E.g., what is the idea/gist? What version of C++ is assumed? What system/compiler (incl. versions) was it tested with? From [the Help Center](https://stackoverflow.com/help/promotion): *"...always explain why the solution you're presenting is appropriate and how it works"*. Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/44452404/edit), not here in comments (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen May 12 '22 at 21:40
24

There is also a POSIX library for POSIX operating systems.

Check for compatibility:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>

void *task(void *argument){
    char* msg;
    msg = (char*)argument;
    std::cout << msg << std::endl;
}

int main(){
    pthread_t thread1, thread2;
    int i1, i2;
    i1 = pthread_create(&thread1, NULL, task, (void*) "thread 1");
    i2 = pthread_create(&thread2, NULL, task, (void*) "thread 2");

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    return 0;
}

Compile with -lpthread.

POSIX Threads

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hohenheimsenberg
  • 935
  • 10
  • 25
23

When searching for an example of a C++ class that calls one of its own instance methods in a new thread, this question comes up, but we were not able to use any of these answers that way. Here's an example that does that:

Class.h

class DataManager
{
public:
    bool hasData;
    void getData();
    bool dataAvailable();
};

Class.cpp

#include "DataManager.h"

void DataManager::getData()
{
    // perform background data munging
    hasData = true;
    // be sure to notify on the main thread
}

bool DataManager::dataAvailable()
{
    if (hasData)
    {
        return true;
    }
    else
    {
        std::thread t(&DataManager::getData, this);
        t.detach(); // as opposed to .join, which runs on the current thread
    }
}

Note that this example doesn't get into mutex or locking.

livingtech
  • 3,570
  • 29
  • 42
  • 9
    Thanks for posting this. Note that the general form of invoking a thread on instance method goes something like this: Foo f; std::thread t(&Foo::Run, &f, args...); (where Foo is a class that has 'Run()' as a member function). – Jay Elston Jan 08 '19 at 19:44
  • 8
    Thanks for posting this. I seriously don't understand why all threading examples use global functions. – hkBattousai Feb 15 '20 at 13:00
  • Change this to shared_from_this if current Class is derived from enable_shared_from_this. – Eugene Feb 01 '21 at 15:39
15

Unless one wants a separate function in the global namespace, we can use lambda functions for creating threads.

One of the major advantage of creating a thread using lambda is that we don't need to pass local parameters as an argument list. We can use the capture list for the same and the closure property of lambda will take care of the lifecycle.

Here is sample code:

int main() {
    int localVariable = 100;

    thread th { [=]() {
        cout << "The value of local variable => " << localVariable << endl;
    }};

    th.join();

    return 0;
}

By far, I've found C++ lambdas to be the best way of creating threads especially for simpler thread functions.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Daksh Gupta
  • 7,554
  • 2
  • 25
  • 36
9

It largely depends on the library you decide to use. For instance, if you use the wxWidgets library, the creation of a thread would look like this:

class RThread : public wxThread {

public:
    RThread()
        : wxThread(wxTHREAD_JOINABLE){
    }
private:
    RThread(const RThread &copy);

public:
    void *Entry(void){
        //Do...

        return 0;
    }

};

wxThread *CreateThread() {
    //Create thread
    wxThread *_hThread = new RThread();

    //Start thread
    _hThread->Create();
    _hThread->Run();

    return _hThread;
}

If your main thread calls the CreateThread method, you'll create a new thread that will start executing the code in your "Entry" method. You'll have to keep a reference to the thread in most cases to join or stop it.

More information is in the wxThread documentation.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
LorenzCK
  • 7,411
  • 2
  • 36
  • 28
  • 1
    You forgot to delete the thread. Perhaps you meant to create a *detached* thread? – aib Nov 05 '08 at 18:57
  • 1
    Yup right, I extracted the code from some code I'm currently working on and of course the reference to the thread is stored somewhere in order to join, stop and delete it later on. Thanks. :) – LorenzCK Nov 06 '08 at 16:06