在这个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()中注册。
答案 0 :(得分:1)
只需使用两个计数器和一个布尔值来实现基本&#34;取一个数字&#34;方案
一个计数器released_thread
表示可以继续执行哪个线程。这在逻辑上等同于&#34;现在服务&#34;指示器。
另一个,next_waiter
,表示接下来哪个线程等待。这在逻辑上等同于将要采用的下一个数字
布尔值表示是否允许线程继续进行以及何时完成,因此执行程序知道何时调用下一个数字。
算法如下:
等待:
获取锁定。
注意next_waiter
变量的值并将其递增。
广播(通知全部)条件变量。
等待条件变量,直到布尔值为true且released_thread
计数器等于步骤2中记录的值。
解锁。
完成后,获取锁定,将布尔值设置为false,广播条件变量,然后释放锁定。
<强>执行强>:
获取锁定。
等待条件变量,直到布尔值为false且next_waiter
不等于released_thread
。
递增released_thread
并将布尔值设置为true。
广播条件变量。
转到第2步。