Soumyajit Roy
Soumyajit Roy

Reputation: 463

Synchronise two threads passing events between each other

I am new to windows c++ programming. Please see the below code where I want to make the two threads synchronized. The first thread should print "Hello" then pass the control/event to the second thread. Not sure how to do it. As of now I am using Sleep(1000). But if I dont use Sleep it result into undefined behavior. Please help...

#include <windows.h>
#include <process.h>
#include <iostream>

void thread1(void*);
void thread2(void*);

int main(int argc, char **argv) {
    _beginthread(&thread1,0,(void*)0);
    _beginthread(&thread2,0,(void*)0);
    Sleep(1000);
}

void thread1(void*)
{
    std::cout<<"Hello "<<std::endl;
}
void thread2(void*)
{
    std::cout<<"World"<<std::endl;
}

Upvotes: 1

Views: 4734

Answers (2)

shivakumar
shivakumar

Reputation: 3407

Here is the simplified version to handle your situation.

You are creating 2 threads to call 2 different function. Ideally thread synchronization is used to serialize same code between threads but in your case it is not the need. You are trying to serialize 2 threads which are no way related to one another. Any how you can wait for each thread to finish by not making async call.

#include <windows.h>
#include <process.h>
#include <iostream>
#include<mutex>

using namespace std;

void thread1(void*);
void thread2(void*);

int main(int argc, char **argv) {

    HANDLE h1 = (HANDLE)_beginthread(&thread1,0,(void*)0);
    WaitForSingleObject(h1,INFINITE);

    HANDLE h2 = (HANDLE)_beginthread(&thread2,0,(void*)0);
    WaitForSingleObject(h2,INFINITE);

}

void thread1(void*)
{
    std::cout<<"Hello "<<std::endl;
}
void thread2(void*)
{
    std::cout<<"World"<<std::endl;
}

You can group both beginthread in single function and call that function in while loop if you want to print multiple times.

 void   fun()
  {     
     HANDLE h1 = (HANDLE)_beginthread(&thread1,0,(void*)0);
    WaitForSingleObject(h1,INFINITE);

    HANDLE h2 = (HANDLE)_beginthread(&thread2,0,(void*)0);
    WaitForSingleObject(h2,INFINITE);       
 }

Upvotes: 0

Mike Vine
Mike Vine

Reputation: 9852

The problem is the question you are asking really doesn't make sense. Multiple threads are designed to run at the same time and you're trying to play a game of pass the buck from one thread to another to get sequential serialised behavoir. Its like taking a really complicated tool and ask how it solves what is normally a really easy question.

However, multithreading is a really important topic to learn so I'll try to answer what you need to the best of my ability.

Firstly, I'd recommend using the new, standard C++11 functions and libraries. For windows, you can download Visual Studio 2012 Express Edition to play about with.

With this you can use std::thread, std::mutex and a lot [but not all] of the other C++11 goodies (like std::condition_variable).

To solve your problem you really need a condition variable. This lets you signal to another thread that something is ready for them:

#include <iostream>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <thread>

static std::atomic<bool> ready;
static std::mutex lock;
static std::condition_variable cv;

// ThreadOne immediately prints Hello then 'notifies' the condition variable
void ThreadOne()
{
    std::cout << "Hello ";
    ready = true;
    cv.notify_one();
}

// ThreadTwo waits for someone to 'notify' the condition variable then prints 'World'
// Note: The 'cv.wait' must be in a loop as spurious wake-ups for condition_variables are allowed
void ThreadTwo()
{
    while(true)
    {
         std::unique_lock<std::mutex> stackLock(lock);
         cv.wait(stackLock);
         if(ready) break;
    }
    std::cout << "World!" << std::endl;
}

// Main just kicks off two 'std::thread's. We must wait for both those threads
// to finish before we can return from main. 'join' does this - its the std 
// equivalent of calling 'WaitForSingleObject' on the thread handle. its necessary
// to call join as the standard says so - but the underlying reason is that
// when main returns global destructors will start running. If your thread is also
// running at this critical time then it will possibly access global objects which
// are destructing or have destructed which is *bad*
int main(int argc, char **argv)
{
    std::thread t1([](){ThreadOne();});
    std::thread t2([](){ThreadTwo();});
    t1.join();
    t2.join();
}

Upvotes: 6

Related Questions