为c ++中的线程提供关键部分

时间:2016-04-08 09:17:31

标签: c++ multithreading mutex

在这个c ++程序中,我创建了10个线程,它们相互竞争以获取关键部分。这意味着我使用条件变量作为下面的代码。该程序中的调度程序将一次授予一个线程进入关键部分。但是有一个微妙的问题。当调度程序授予要进入的线程时,它会将ready_pipe变量设置为true。如果此时出现一个新线程(在消费者设置ready_pipe = flase之前),新手线程将在未经许可的情况下穿过关键部分。

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

using namespace std;

std::condition_variable con_var_pipe;
bool ready_pipe = false;
std::mutex pipe_mutex;

bool critical_section_is_free=true;

void dispatcher()
{

    while(true)
    {

        if(critical_section_is_free)
        {
            critical_section_is_free=false;

            // send signal to a thread to enter critical section
            std::lock_guard<std::mutex> lk(pipe_mutex);
            ready_pipe = true;
            con_var_pipe.notify_one();

        }
    }
}


void consumer()
    {
    std::unique_lock<std::mutex> lk(pipe_mutex);

    /* The Problem is Here at below line.When a new thread comes, 
      it will pass through this block because it see ready_pipe is true!!!*/

    con_var_pipe.wait(lk, [] {return ready_pipe;});

    /// critical section starts
    ready_pipe=false;
    /// here accessing pipe is occurring .

    /// critical section ends
    critical_section_is_free=true;


}

 int main()
    {
    std::thread allThreads[10];

    for(int i = 0 ; i<10 ; i++)
    {
        allThreads[i]=std::thread(consumer);
    }

    thread disp(dispatcher);

    for(int i = 0 ; i< 6 ; i++)
    {
        allThreads[i].join();
    }

    disp.join();

    return 0;
}

此外,由于调度程序函数中的while(true)语句并且忙于等待,此代码也不足。

所以问题是:

1-如何在新线程到来时创建互斥。

2 - 如何避免在dispatcher()函数中忙碌等待。

3 - 以及线程如何按顺序提供并在wait()中注册。

1 个答案:

答案 0 :(得分:1)

只需使用两个计数器和一个布尔值来实现基本&#34;取一个数字&#34;方案

一个计数器released_thread表示可以继续执行哪个线程。这在逻辑上等同于&#34;现在服务&#34;指示器。

另一个,next_waiter,表示接下来哪个线程等待。这在逻辑上等同于将要采用的下一个数字

布尔值表示是否允许线程继续进行以及何时完成,因此执行程序知道何时调用下一个数字。

算法如下:

等待

  1. 获取锁定。

  2. 注意next_waiter变量的值并将其递增。

  3. 广播(通知全部)条件变量。

  4. 等待条件变量,直到布尔值为true且released_thread计数器等于步骤2中记录的值。

  5. 解锁。

  6. 完成后,获取锁定,将布尔值设置为false,广播条件变量,然后释放锁定。

  7. <强>执行

    1. 获取锁定。

    2. 等待条件变量,直到布尔值为false且next_waiter不等于released_thread

    3. 递增released_thread并将布尔值设置为true。

    4. 广播条件变量。

    5. 转到第2步。