1.生产者消费者问题(信号量)
参考教材中的生产者消费者算法,创建5个进程,其中两个进程为生产者进程,3个进程为消费者进程。一个生产者进程试图不断地在一个缓冲中写入大写字母,另一个生产者进程试图不断地在缓冲中写入小写字母。3个消费者不断地从缓冲中读取一个字符并输出。为了使得程序的输出易于看到结果,仿照的实例程序,分别在生产者和消费者进程的合适的位置加入一些随机睡眠时间。
可选的实验:在上面实验的基础上实现部分消费者有选择地消费某些产品。例如一个消费者只消费小写字符,一个消费者只消费大写字母,而另一个消费者则无选择地消费任何产品。消费者要消费的产品没有时,消费者进程被阻塞。注意缓冲的管理。
【参考代码】
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <random>
using namespace std;const int n = 10; // 缓冲区大小
queue<char> buffer; // 缓冲区
mutex mtx; // 互斥锁
condition_variable empty, da, xiao; // 条件变量
int flag = -1; // 标志位// 生产者线程A,生成大写字符
void produce_A()
{while (true) {unique_lock<std::mutex> lock(mtx);empty.wait(lock, [] { return buffer.size() < n; }); // 等待缓冲区非满char ch = 'A' + std::rand() % 26; // 生成大写字符buffer.push(ch); // 将字符放入缓冲区da.notify_one(); // 通知消费者有大写字符可用sleep(1);}
}
// 生产者线程a,生成小写字符
void produce_a()
{while (true) {unique_lock<std::mutex> lock(mtx);empty.wait(lock, [] { return buffer.size() < n; }); // 等待缓冲区非满char ch = 'a' + std::rand() % 26; // 生成小写字符buffer.push(ch); // 将字符放入缓冲区xiao.notify_one(); // 通知消费者有小写字符可用sleep(1);}
}
// 消费者线程A,处理大写字符
void consumer_A()
{while (true) {unique_lock<std::mutex> lock(mtx);da.wait(lock, [] { return !buffer.empty(); }); // 等待有大写字符可用char ch = buffer.front(); // 从缓冲区取出字符buffer.pop(); // 移除字符empty.notify_one(); // 通知生产者缓冲区有空位cout << "Consumer A: " << ch << std::endl; // 输出字符sleep(1);}
}
// 消费者线程a,处理小写字符
void consumer_a()
{while (true) {unique_lock<std::mutex> lock(mtx);xiao.wait(lock, [] { return !buffer.empty(); }); // 等待有小写字符可用char ch = buffer.front(); // 从缓冲区取出字符buffer.pop(); // 移除字符empty.notify_one(); // 通知生产者缓冲区有空位cout << "Consumer a: " << ch << std::endl; // 输出字符sleep(1);}
}
// 消费者线程A或a,处理大写或小写字符
void consumer_A_or_a()
{while (true) {unique_lock<std::mutex> lock(mtx);da.wait(lock, [] { return !buffer.empty(); }); // 等待有大写字符可用char ch = buffer.front(); // 从缓冲区取出字符buffer.pop(); // 移除字符empty.notify_one(); // 通知生产者缓冲区有空位cout << "Consumer A or a: " << ch << std::endl; // 输出字符sleep(1);}
}int main()
{thread producerA(produce_A);thread producera(produce_a);thread consumerA(consumer_A);thread consumera(consumer_a);thread consumerAora(consumer_A_or_a);producerA.join();producera.join();consumerA.join();consumera.join();consumerAora.join();return 0;
}
【运行结果】
1、竞争不是很明显 2、某些进程消费了错误的产品
2.实现睡觉的理发师问题(同步互斥方式采用信号量或mutex方式均可)
理发师问题的描述:一个理发店接待室有n张椅子,工作室有1张椅子;没有顾客时,理发师睡觉;第一个顾客来到时,必须将理发师唤醒;顾客来时如果还有空座的话,他就坐在一个座位上等待;如果顾客来时没有空座位了,他就离开,不理发了;当理发师处理完所有顾客,而又没有新顾客来时,他又开始睡觉。
【参考代码】 线程实现睡觉的理发师问题(mutex方式)http://t.csdnimg.cn/JNRne
#include <bits/stdc++.h>
#include <pthread.h>
#include <unistd.h>
using namespace std;pthread_mutex_t Mutex;
int n;
int num;
int flag = -1;void *customer(void *arg)
{while(flag){pthread_mutex_lock(&Mutex);if(num < n){num++;cout << "A customer IN, chairs left:" << n - num << endl;pthread_mutex_unlock(&Mutex); //解锁}else{pthread_mutex_unlock(&Mutex); //解锁cout << "No chairs!" << endl;}}
}void *barber(void *arg){while(flag){if(num > 0){pthread_mutex_lock(&Mutex);num--;cout << "A customer OUT, chairs left:" << n-num << endl;pthread_mutex_unlock(&Mutex); //解锁}}
}int main()
{cout << "input chairs number:" << endl;cin>>n;num = 0;pthread_t Barber, Customer;pthread_mutex_init(&Mutex, NULL);pthread_create(&Barber, NULL, barber, NULL);pthread_create(&Customer, NULL, customer, NULL);sleep(1);flag = 0;pthread_join(Barber, NULL);pthread_join(Customer, NULL);pthread_mutex_destroy(&Mutex);return 0;
}