1

Here I have used 2 mutexes for 2 condition variables. How to decide whether one mutex is sufficient or separate mutexes are required ?

Source:

#include "thread_class.h"

#include <unistd.h>
#include <mutex>
#include <queue>
#include <condition_variable>
#include <iostream>

// Thread_manager class: ***************************************************************************************************************
std::queue<int> queue_m;

std::mutex mutex_k;

bool watch;

std::mutex mutex_x;
std::mutex mutex_y;

std::condition_variable cv_x;
std::condition_variable cv_y;

ThreadManager::ThreadManager() : obj_thread_B_( &B::Run, &obj_class_B_),
                                 obj_thread_A_( &A::Run, &obj_class_A_ )
{
    watch = false;
}

ThreadManager::~ThreadManager()
{
    obj_thread_A_.join();
    obj_thread_B_.join();
}

void A::Run()
{
    while( 1 )
    {
        std::unique_lock<std::mutex> lk( mutex_x );
        while (watch == false)
            cv_x.wait( lk );

        std::cout << "\nA class\n";

        someint++;
        queue_m.push( someint );

        cv_y.notify_all();

        // some time consuming operation
        for (int t = 0; t < 1000000; t++)
        {
        }
    }
}

void B::Run()
{
    while( 1 )
    {
        std::cout << "\nB class\n";

        if (queue_m.size() > 0)
        {
            int temp = queue_m.front();
            std::cout << "\nTaken out: " << temp;
            queue_m.pop();

            cv_x.notify_all();
        }
        else
        {
            std::unique_lock<std::mutex> lk( mutex_y );
            watch = true;

            cv_x.notify_all();

            cv_y.wait( lk );
        }
     }
}
Aquarius_Girl
  • 21,790
  • 65
  • 230
  • 411
  • 1
    @Ron i meant am i supposed to use a mutex for 2 condition variables or 2 mutexes for 2 condition variables? – Aquarius_Girl Jul 27 '18 at 10:59
  • 2
    I'm not sure why you got all the downvotes. I think this is a good question. Perhaps it's because you dropped a large block of code without introducing it or explaining why it's there or what you're trying to do with it rather than just expecting everyone to study it and figure that out for themselves. – Gabriel Staples Jul 25 '19 at 20:52

2 Answers2

4

@Abhijit is right: it depends on how many race conditions you have. Here are some more details to determine this.

  1. Get out a piece of paper. On the right, list down the page all of the protected resources you want to guarantee any thread exclusive access to while it's using it.
  2. On the left side of the page, list down the page all of the threads that might need these resources. If you know simply it will be > 1 thread, you can just write "thread 1" and "thread 2" to represent an infinite number of threads.
  3. Draw an arrow from each thread on the left to all resources it needs on the right.
  4. Circle all arrow head junctions on the right where there is more than one arrow head pointing to a single resource. Count the number of circles. That's how many race conditions you have for this module, and that's how many separate mutexes you need.

Example I just drew up. This example has 3 race conditions (notice the 3 circles) and therefore requires 3 separate mutexes:

enter image description here

  1. Now evaluate the left: can you remove any threads on the left by combining functionality from multiple threads into a single thread? If so, do that. Conversely: do you need to split any thread into 2 or more threads to separate functionality? If so, do that.
  2. Evaluate the right: can you combine any resources on the right into 1, to be protected by a single mutex? Ex: try combining "UART write" and "UART read" into a single protected resource. Does that work? Well, if the "read-only thread" and the "write-only thread" must read and write, respectively, at exactly the same time, in parallel (ie: they can't wait for eachother and do it in serial), then NO! This will NOT work! They must remain separate resources! But if they can wait for each other and do these operations in serial, based on your project and design, then YES! You can combine these 2 things, protecting them by 1 single mutex now, and remove the extra mutex.
  3. Once you've evaluated the left and right, combining or splitting threads and resources as necessary for your design, repeat steps 3 and 4 above. Count the circles. That's how many race conditions you have, and consequently how many distinct mutexes you need for your design.

Notice how much leeway and control you have here. A lot of this is up to your specific architectural design. You are the architect and designer. You might come up with a different solution and number of mutexes than someone else, and there are tradeoffs and pros and cons to each design. This might be just fine. Keep that in mind: YOU ARE THE DESIGNER, and designs can vary. Sometimes there is no perfect design, and you just have to make tradeoffs. Regardless though, the above methodical process will help you determine how many mutexes you need for your specific design.

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
3

That depends on total number of race condition in your process. Based on different race condition in your process you will take a decision about number of mutex you really need to handle all the race conditions. Please read below answers which will help your understand about race condition.

What is a race condition?

Abhijit Pritam Dutta
  • 5,521
  • 2
  • 11
  • 17