【发布时间】:2022-01-08 20:39:11
【问题描述】:
我正在尝试解决以下问题:“这个类比是基于一个假设的理发店有一个理发师。理发师在剪裁室有一把理发椅和一个包含许多椅子的等候室。当理发师剪完一个顾客的头发,他把顾客打发走了,去候车室看看有没有其他人在等,如果有,他把其中一个人带回椅子上剪头发。如果没有,他回到椅子上睡去。
每位顾客到达时都会看看理发师在做什么。如果理发师在睡觉,顾客会叫醒他并坐在剪裁室的椅子上。如果理发师在剪头发,顾客会留在等候室。如果候诊室里有空椅子,顾客就坐在上面等待轮到他们。如果没有空闲的椅子,顾客就会离开。 "
我的整个代码如下:
// Example program
#include <iostream>
#include <string>
#include <mutex>
#include <thread>
#include <chrono>
#include <atomic>
#include <deque>
#include <vector>
#include <condition_variable>
using namespace std;
const unsigned int NUM_CHAIRS = 2;
const unsigned int NUM_CUSTOMERS = 1;
// In a barbershop, customers are coming in and there is only one barber. If the barber is cutting a
// customers hair, the customer will wait. There are only a limited amount of chairs for the customer
// to wait on. If the chairs are full, then the customer will leave and try again later.
struct Barbershop
{
public:
Barbershop(): num_waiting(0){};
condition_variable cv; // Acts like a receptionist
atomic<int> num_waiting; // Number of customers waiting on chairs
mutex cout_mtx;
};
class Barber
{
public:
Barber(Barbershop& shop): mem_shop(shop), hislife(&Barber::work, this){};
void work()
{
unique_lock<mutex> lk(b_mu);
if(mem_shop.num_waiting == 0)
{
mem_shop.cout_mtx.lock();
cout << "Barber sleeping...\n";
mem_shop.cout_mtx.unlock();
}
mem_shop.cv.wait(lk, [this]{return mem_shop.num_waiting > 0;}); // []{return mem_shop.num_waiting}
mem_shop.cout_mtx.lock();
cout << "Time to cut some hair!\n";
mem_shop.cout_mtx.unlock();
lk.unlock();
mem_shop.cv.notify_one();
this_thread::sleep_for(chrono::milliseconds(100));
mem_shop.num_waiting--;
};
~Barber()
{
hislife.join();
}
int jn;
mutex b_mu;
Barbershop& mem_shop;
thread hislife;
};
class Customer
{
public:
Customer(Barbershop& shop, int name_id): mem_shop(shop), name(name_id), hislife(&Customer::tryGetHaircut, this){};
void tryGetHaircut()
{
if(mem_shop.num_waiting == NUM_CHAIRS)
{
mem_shop.cout_mtx.lock();
cout << name <<"'s wait was too long. Leaving!\n";
mem_shop.cout_mtx.unlock();
}
else
{
mem_shop.num_waiting++;
std::unique_lock<mutex> lk(c_mu);
mem_shop.cv.wait(lk);
mem_shop.cout_mtx.lock();
cout << name << " is getting haircut!\n";
mem_shop.cout_mtx.unlock();
}
};
~Customer()
{
hislife.join();
}
mutex c_mu;
Barbershop& mem_shop;
thread hislife;
unsigned int name;
};
int main()
{
Barbershop mybarbershop;
Barber dan();
vector<Customer*> customers;
customers.reserve(NUM_CUSTOMERS-1);
for(unsigned int i=0; i<NUM_CUSTOMERS; i++)
{
customers.push_back(new Customer(mybarbershop, i+1));
}
for(auto s : customers)
{
delete s;
}
cout << "Program Finished!\n";
return 0;
}
但是,我的代码甚至没有进入 Barbers 线程,并且似乎被锁定在条件变量上。在解决这个问题时,我在逻辑/语法方面有什么明显的问题吗?
我仍然是初学者,因此我们将不胜感激任何有关该主题的帮助。
【问题讨论】:
-
OT:
std::vector<std::unique_ptr<Customer>> customers;可能是更好的选择。 -
你也根本不需要
cout_mtx。写入std::cout本身保证是线程安全的。参见,例如,stackoverflow.com/q/6374264/580083。在另一个锁定的互斥锁下获取互斥锁会产生死锁。 -
@DanielLangr 它是线程安全的,但是由于同时刷新缓冲区,您可能会混淆行。
-
@DanielLangr 感谢您的回复!我会阅读链接并尝试一下。您是否也碰巧尝试过运行代码?
-
@JorgeBellon AFAIK,甚至
endl或flush仅在库级别解析刷新。操作系统仍然可以使用一些内部缓冲区,这些缓冲区通常无法从用户空间进行控制。
标签: c++ multithreading