如何确定我需要多少个互斥锁?

时间:2018-07-27 10:48:44

标签: c++ multithreading mutex

在这里,我为2个条件变量使用了2个互斥体。如何确定一个互斥量足够还是需要单独的互斥量?

来源:

#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 );
        }
     }
}

2 个答案:

答案 0 :(得分:1)

这取决于您处理中race condition的总数。根据处理过程中的不同race condition,您将决定处理所有race conditions所需的互斥量。请阅读以下答案,这将有助于您了解race condition

What is a race condition?

答案 1 :(得分:1)

@Abhijit is right:这取决于您拥有多少比赛条件。确定这些的更多详细信息。

  1. 拿出一张纸。在右侧的页面上,列出您要保证在使用该线程时所有线程专有访问权的所有受保护资源
  2. 在页面左侧,在页面下方列出所有可能需要这些资源的线程。如果仅知道线程数> 1,就可以编写“线程1”和“线程2”来表示无限数量的线程。
  3. 从左侧的每个线程向右侧的所有资源绘制箭头。
  4. 在右边有所有指向单个资源的多个箭头的箭头处圈起来。计算圆圈数。这就是您对该模块具有的竞争条件,也就是您需要多少个单独的互斥体。

我只是画了一个例子。此示例具有 3 个竞争条件(请注意3个圆圈),因此需要 3 个单独的互斥体:

enter image description here

  1. 现在评估左侧:您可以通过将多个线程中的功能合并为单个线程来删除左侧的任何线程吗?如果是这样,请执行此操作。相反:您是否需要将任何线程分成2个或更多线程以分离功能?如果是这样,请这样做。
  2. 评估权限:您可以将右侧的任何资源合并为1,以使用单个互斥锁进行保护吗?例如:尝试将“ UART写”和“ UART读”组合到受单个保护的资源中。可以吗?好吧,如果“只读线程”和“只写线程”必须分别在完全相同的时间分别并行地读写 (即:它们不能互相等待)并以串行方式执行),然后否!这行不通!他们必须保留单独的资源!但是,如果他们可以彼此等待并根据您的项目和设计以串行方式执行这些操作,那么可以!您可以将这两件事结合起来,现在用1个单个互斥锁保护它们,然后删除多余的互斥锁。
  3. 评估完左右后,根据设计需要组合或拆分线程和资源,然后重复上述步骤3和4。数一下圈子。那就是您有多少竞争条件,因此您的设计需要多少个不同的互斥体。

请注意您在这里有多少余地和控制权。其中大部分取决于您的特定建筑设计。您是建筑师和设计师。您可能会想出与其他人不同的解决方案和互斥量,并且每种设计都有其优缺点。 请记住:您是设计师,设计可能会有所不同。有时没有完美的设计,您只需要进行权衡即可。无论如何,上述有条理的过程将帮助您确定特定设计所需的互斥量。