生产者-消费者问题(进程同步问题)
最近在学线程,在加上操作系统也在学线程,于是乎有了这篇文章
问题描述:
一群生产者进程在生成产品,并将这些产品提供给消费者进程去消费. 他们之间有一个公共的缓冲区用来存放产品,当产品为空时消费者不能消费,当产品为满时生产者不能生产
CPP实现
- 利用mutex 互斥量 来对缓存区的操作进行加锁
#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>
constexpr int n = 10; // 缓存区大小
int in = 0, out = 0; // 生产指针,消费指针
int full = 0, empty = 10; // 空与满
int buffer[10]; // 缓存区
std::mutex mtx; // 互斥量
/**
* 生产者函数
*/
void producer() {
do {
while (full == n)
;
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::scoped_lock lock(mtx);
buffer[in] = 1;
in = (in + 1) % n;
std::cout << "生产者生产:" << in << "\n";
empty--;
full++;
}
} while (true);
}
/**
* 消费者函数
*/
void consumer() {
do {
while (empty == n)
;
{
std::scoped_lock lock(mtx);
buffer[out] = 0;
out = (out + 1) % n;
std::cout << "消费者消费:" << out << "\n";
empty++;
full--;
}
std::this_thread::sleep_for(std::chrono::seconds(2));
} while (true);
}
int main() {
std::thread t1{producer};
std::thread t2{consumer};
t1.join();
t2.join();
return 0;
}
Java实现
用Storage对象模拟缓存区,关键代码如下
/**
* 存储类
*/
public class Storage {
private Product[] products = new Product[10];
private int top = 0;
public synchronized void push(Product product){
while(top == products.length){
try{
System.out.println("producer wait");
wait(); //缓冲区满,无法生产,则阻塞
}catch (InterruptedException e){
e.printStackTrace();
}
}
products[top++] = product;
System.out.println(Thread.currentThread().getName()+" 生产了 "+product);
System.out.println("producer notifyAll");
notifyAll(); //生产出新的产品,唤醒消费者进程
}
public synchronized Product pop(){
while (top==0){
try{
System.out.println("consumer wait");;
wait(); //缓冲区空,无法消费,阻塞
}catch (InterruptedException e){
e.printStackTrace();
}
}
--top;
Product p = new Product(products[top].getId(),products[top].getName());
products[top] = null;
System.out.println(Thread.currentThread().getName()+ " 消费了 "+p);
System.out.println("consumer notifyAll");
notifyAll(); //消费了产品,唤醒生产者
return p;
}
}
public class Producer implements Runnable{
private Storage storage;
public Producer(Storage storage){
this.storage = storage;
}
@Override
public void run() {
int i=0;
Random r = new Random();
while(i<10){
i++;
Product product = new Product(i,"电话"+r.nextInt(100));
storage.push(product);
}
}
}
public class Consumer implements Runnable{
private Storage storage;
public Consumer(Storage storage){
this.storage = storage;
}
@Override
public void run() {
int i=0;
while (i<10){
i++;
storage.pop();
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义