C++ and pthread simple program help

  • Context: C/C++ 
  • Thread starter Thread starter perplexabot
  • Start date Start date
  • Tags Tags
    C++ Program
Click For Summary

Discussion Overview

The discussion revolves around a C++ program utilizing pthreads for multithreading. Participants explore issues related to thread execution and synchronization, particularly focusing on the behavior of the main thread in relation to created threads.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Exploratory

Main Points Raised

  • One participant shares a code snippet that fails to produce output from a thread, questioning why the output appears only when calling the function directly in the main thread.
  • Another participant suggests that the main thread exits before the created thread has a chance to complete, recommending the use of pthread_join for synchronization.
  • A later reply confirms that pthread_join ensures the main thread waits for the created thread to finish, contrasting this with the unpredictability of using sleep or other unsynchronized methods.
  • One participant provides a more complex example of multithreading using C++ standard libraries, illustrating synchronization between threads with event handling.
  • Another participant mentions the use of modern libraries like BoostThread for simpler thread management.

Areas of Agreement / Disagreement

Participants generally agree on the importance of thread synchronization, particularly the role of pthread_join. However, there are differing opinions on the best practices for managing threads, including the use of modern libraries versus pthreads.

Contextual Notes

Some participants discuss the subtleties of thread synchronization and the potential for race conditions, highlighting the complexity of multithreading in C++. Limitations in the original code and assumptions about thread execution timing are noted but not resolved.

Who May Find This Useful

Readers interested in C++ programming, multithreading concepts, and synchronization techniques may find this discussion beneficial.

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   Reactions: 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.
 

Similar threads

Replies
6
Views
2K
  • · Replies 25 ·
Replies
25
Views
3K
Replies
89
Views
7K
  • · Replies 6 ·
Replies
6
Views
1K
  • · Replies 17 ·
Replies
17
Views
2K
  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 6 ·
Replies
6
Views
11K
  • · Replies 9 ·
Replies
9
Views
3K
  • · Replies 30 ·
2
Replies
30
Views
5K
  • · Replies 32 ·
2
Replies
32
Views
4K