C/C++ C++ and pthread simple program help

  • Thread starter Thread starter perplexabot
  • Start date Start date
  • Tags Tags
    C++ Program
AI Thread Summary
The discussion revolves around a C++ program using pthreads to demonstrate multithreading. The user encounters an issue where the output from a thread does not appear unless a function is called directly in the main function, leading to confusion about thread execution timing. It is clarified that the main function exits before the thread has a chance to complete, suggesting the use of pthread_join to ensure the main thread waits for the created thread to finish. The conversation also touches on synchronization methods and the potential for race conditions if not handled properly. Ultimately, the user expresses gratitude for the assistance received, noting that their interview focused on different topics but appreciated the thread knowledge gained.
perplexabot
Gold Member
Messages
328
Reaction score
5
Hey all. I am currently trying to brush up on my multithreading "skills" (I dare say) that I learned in my undergrad class. I have the following code that I am trying to run:

Code:
#include <pthread.h>
#include <iostream>
using namespace std;
void* func1(void*);

int main(int argc, char** argv){
        pthread_t t1;
        //func1(NULL);
        int rc = pthread_create(&t1,NULL,func1,NULL);
        func1(NULL);
        return 0;
}

void* func1(void* trash){
    for(int i = 0; i < 10; i++){
        cout<<i<<endl;
    }
}

I am compiling using g++ with the following:
Code:
g++ -pthread main.cpp
No errors are encountered BUT when I execute
Code:
./a.out
in the terminal I don't get anything. I was hoping to get the sequence of numbers from 0 to 9...

Any help on this would be greatly appreciated as I have a job interview tomorrow and I believe I will be questioned about threads : /

Thank you for reading.EDIT------------------------------------------------------
Hey again. So I have been playing around with this little program and I ran into something interesting (maybe not so interesting if you know what is going on... I don't tho!). If i place the following extra line in the code (a snippet):
Code:
int main(int argc, char** argv){
        pthread_t t1;
        //func1(NULL);
        int rc = pthread_create(&t1,NULL,func1,NULL);
        func1(NULL); //<---- extra line
        return 0;
}

I am able to see the output of func1 twice on the terminal! Which means the thread is working and so is the function call to func1 in main.

So why is it that when I remove this extra line I am not able to see the new thread's function output?
 
Last edited by a moderator:
Technology news on Phys.org
You start a thread but then exit your main method before the thread had a chance to complete. In this particular case you may want to consider using pthread_join [1], but in general there are many ways to synchronize the behavior of multiple threads, each with its own set of critical subtleties.

[1] http://linux.die.net/man/3/pthread_join
 
Filip Larsen said:
You start a thread but then exit your main method before the thread had a chance to complete. In this particular case you may want to consider using pthread_join [1], but in general there are many ways to synchronize the behavior of multiple threads, each with its own set of critical subtleties.

[1] http://linux.die.net/man/3/pthread_join
Thank you! I actually just finished experimenting with join(). So you are saying that if main() just so happened to be running for a bit longer (like say with a sleep() or a join()),my created thread would have executed? So join() guarantees this to happen.?.
 
perplexabot said:
So you are saying that if main() just so happened to be running for a bit longer (like say with a sleep() or a join()),my created thread would have executed? So join() guarantees this to happen.?

Yes, the call to join() will, in normal situations, only return once the thread has terminated.

If you try use a sleep or a similar unsynchronized approach to make the thread complete before main() there would be no such guarantee. In some situations main() may terminate before the thread and in other situations it may be the opposite. The code would then have a race-condition [1] which is almost always a bad thing.

[1] http://en.wikipedia.org/wiki/Race_condition
 
  • Like
Likes harborsparrow
Here's an example std c++ code that spawns two threads, with the ability for the main thread to pause, continue, or terminate the process. Both threads read from a "current" array at the same time, with the "producer" thread updating the "other" array, and the "consumer" thread displaying the "current" array. Each thread uses an event for synchronization, and each thread swaps it's own pair of pointers to alternate between the two arrays, a type of double buffering. Note that .join() is only used when waiting for the threads to terminate.

Code:
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>

struct test
{
    double x[10], y[10];
    double *cxpx = &x[0];               // ptrs for change_x
    double *cxpy = &y[0];
    double *pxpx = &x[0];               // ptrs for print_x
    double *pxpy = &y[0];
    std::atomic<bool> stop = false;
    std::atomic<bool> pause = false;
};

class handle_Event
{
private:
    bool signalled;
    std::condition_variable_any c_v;
    std::mutex mtx;

public:
    handle_Event()
    {
        signalled = false;
    }
    ~handle_Event()
    {
    }
    void signal(void)
    {
        std::lock_guard<std::mutex> lck(mtx);
        signalled = true;
        c_v.notify_one();
    }
    void reset(void)
    {
        std::lock_guard<std::mutex> lck(mtx);
        signalled = false;
    }
    bool wait(void)
    {
        std::lock_guard<std::mutex> lck(mtx);
        while (!signalled)
            c_v.wait(mtx);
        return signalled;
    }
};

handle_Event hndl_change_x, hndl_print_x, hndl_continue;

void change_x(test &t)
{
    while (1){
        hndl_change_x.wait();           // wait
        hndl_change_x.reset();
        if (t.stop.load())              // exit if stop flag set
            break;
        const double f = t.cxpx[0];
        for (uint16_t i = 0; i < 10; i++)
            t.cxpy[i] = ((i + 1) % 10) ? t.cxpx[i + 1] : f;
        std::swap(t.cxpx, t.cxpy);
        hndl_print_x.signal();          // ready for print
    }
}

void print_x(test &t)
{
    while (1){
        hndl_print_x.wait();            // wait
        hndl_print_x.reset();
        if (t.pause.load()){            // pause if pause set
            hndl_continue.wait();
            hndl_continue.reset();
        }
        if (t.stop.load())              // exit if stop flag set
            break;
        hndl_change_x.signal();         // ready for change
        for (uint16_t j = 0; j < 10; j++)
            std::cout << t.pxpx[j] << " ";
        std::cout << std::endl;
        std::swap(t.pxpx, t.pxpy);
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
}

int main(void)
{
    double x0[] = { 0., 1., 2., 3., 4., 5., 6., 7., 8., 9. };
    test var;
    for (uint16_t i = 0; i < 10; i++) var.x[i] = x0[i];
    char hit = 0;

    std::thread thread_change_x(change_x, std::ref(var));
    std::thread thread_print_x(print_x,   std::ref(var));
    hndl_print_x.signal();          // start with print

    while (1){                      // wait for input
        if ((hit = std::cin.get()) == 'x')
            break;
        if ((hit == 'p') && (var.pause.load() == false))
            var.pause.store(true);
        if ((hit == 'c') && (var.pause.load() == true)){
            var.pause.store(false);
            hndl_continue.signal();
        }
    }
    var.stop.store(true);           // stop threads
    hndl_change_x.signal();
    hndl_print_x.signal();
    hndl_continue.signal();
    thread_change_x.join();         // wait for child threads to stop
    thread_print_x.join();
    return 0;
}
 
Thank you guys for your replies and help. I actually read them right before my interview which provided me with some confidence. Nothing about threads was asked (mostly C++ sockets), I got a call from them after for a second interview. Maybe my thread studying will come in handy for that. Thanks again.
 
If you just want to open a thread prefer a modern lib like BoostThread. Simple to use, simple to understand. Boost is very popular.
 
Back
Top