简体   繁体   中英

Boost Mutex between threadpool and process

I have 4 functions in class Test:

void Test::A()
{
    boost::lock_guard<boost::mutex> lock(mutex);
    cout << "A!" << endl;
}

void Test::B()
{
    boost::lock_guard<boost::mutex> lock(mutex);
    cout << "B!" << endl;
}

void Test::C()
{
    boost::lock_guard<boost::mutex> lock(mutex);
    cout << "C!" << endl;
}

void Test::D()
{
    boost::lock_guard<boost::mutex> lock(mutex);
    cout << "D!" << endl;
}

If I call Test::A through Test::D in alphabetical order, over and over in a loop and bind them to a boost thread_pool, it works fine for the most part. However, on occasion, the cout statements get printed out of order. So I might see ABCDABCDABCDAB DC . From what I understand it just has to do with when the thread_pool gets a new thread, and I cannot control in which order they get called in.

My issue is that I need C() and D() to be called sequentially (when they need to be called), and do not care about the order of A() and B() relative to each other and C() and D(). So instead of calling C and D through the thread_pool, I am now calling it through the main process, keeping all mutexes. The program hangs right before the cout statement in C when I attempt to call all the functions in a loop again. I am stumped as to why this is the case. Can I not have a mutex across the main process and it's threads?

Despite the simplistic nature of these functions, I am unable to just combine the logic of C and D, as these functions will eventually be upgraded to event based functions. The loop calling them over and over is just a dummy loop to simulate real life events. D will ALWAYS be called after C, but it may or may not be called.

For example:

ABCD

ABCCD

AD

ABCCC

If C and D can be triggered by separate events (ie you can't just call them sequentially in the same thread), but D must not be executed before C, you'll need to use a Condition Variable or some other means of synchronization (a Semaphore, perhaps).

As you're already using boost, I recommend having a look at Boost Condition Variables

This is entirely normal. When you start two threadpool threads, first A and then B, then there's no guarantee whatsoever that A gets to the cout statement before B does. It is merely likely . The bug you created is called a "threading race", a very common bug in code that uses threads and notoriously difficult to diagnose and fix.

These threads run at their own pace. If the operating system pre-empts A but not B, for example when it wants to allow another thread in another process to run, then B will certainly race ahead of A and get to the cout statement first. The only simple way to ensure that these cout statements are executed strictly sequentially is by using one thread.

If you want to maintain an order of execution, look into semaphore. Lock is FIFO, so which-ever thread gets a hold of the lock first will get executed first. To ensure C is called before D, do something like this:

C : increment semaphore by 1
D : decrement semaphore by 1

If semaphore start at 0, D will only be able to decrement semaphore once semaphore is at 1 (incremented by C already). You can use a binary semaphore for this case. The possible values will be 0 or 1.

You might have a fifo queue to order C/D events and process and remove the first element in that queue, if it has a result (maybe thread E). If the threads C and D might disturb each other, make one thread CD, only.

If the C event is actually triggering the D event you might consider a parallel pipeline C->D.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM