Phtreads实现producer_consumer

并发编程:生产者消费者问题解决方案
本文介绍了一个使用线程解决生产者消费者问题的示例程序,包括初始化队列、队列操作以及生产者、消费者线程的实现。
/*
 *	File	: pc.c
 *
 *	Title	: Demo Producer/Consumer.
 *
 *	Short	: A solution to the producer consumer problem using
 *		pthreads.	
 *
 *	Long 	:
 *
 *	Author	: Andrae Muys
 *
 *	Date	: 18 September 1997
 *
 *	Revised	:
 */

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define QUEUESIZE 10
#define LOOP 20

void *producer (void *args);
void *consumer (void *args);

typedef struct {
	int buf[QUEUESIZE];
	long head, tail;
	int full, empty;
	pthread_mutex_t *mut;
	pthread_cond_t *notFull, *notEmpty;
} queue;

queue *queueInit (void);
void queueDelete (queue *q);
void queueAdd (queue *q, int in);
void queueDel (queue *q, int *out);

int main ()
{
	queue *fifo;
	pthread_t pro, con;

	fifo = queueInit ();
	if (fifo ==  NULL) {
		fprintf (stderr, "main: Queue Init failed.\n");
		exit (1);
	}
	pthread_create (&pro, NULL, producer, fifo);
	pthread_create (&con, NULL, consumer, fifo);
	pthread_join (pro, NULL);
	pthread_join (con, NULL);
	queueDelete (fifo);

	return 0;
}

void *producer (void *q)
{
	queue *fifo;
	int i;

	fifo = (queue *)q;

	for (i = 0; i < LOOP; i++) {
		pthread_mutex_lock (fifo->mut);
		while (fifo->full) {
			printf ("producer: queue FULL.\n");
			pthread_cond_wait (fifo->notFull, fifo->mut);
		}
		queueAdd (fifo, i);
		pthread_mutex_unlock (fifo->mut);
		pthread_cond_signal (fifo->notEmpty);
		usleep (100000);
	}
	for (i = 0; i < LOOP; i++) {
		pthread_mutex_lock (fifo->mut);
		while (fifo->full) {
			printf ("producer: queue FULL.\n");
			pthread_cond_wait (fifo->notFull, fifo->mut);
		}
		queueAdd (fifo, i);
		pthread_mutex_unlock (fifo->mut);
		pthread_cond_signal (fifo->notEmpty);
		usleep (200000);
	}
	return (NULL);
}

void *consumer (void *q)
{
	queue *fifo;
	int i, d;

	fifo = (queue *)q;

	for (i = 0; i < LOOP; i++) {
		pthread_mutex_lock (fifo->mut);
		while (fifo->empty) {
			printf ("consumer: queue EMPTY.\n");
			pthread_cond_wait (fifo->notEmpty, fifo->mut);
		}
		queueDel (fifo, &d);
		pthread_mutex_unlock (fifo->mut);
		pthread_cond_signal (fifo->notFull);
		printf ("consumer: recieved %d.\n", d);
		usleep(200000);
	}
	for (i = 0; i < LOOP; i++) {
		pthread_mutex_lock (fifo->mut);
		while (fifo->empty) {
			printf ("consumer: queue EMPTY.\n");
			pthread_cond_wait (fifo->notEmpty, fifo->mut);
		}
		queueDel (fifo, &d);
		pthread_mutex_unlock (fifo->mut);
		pthread_cond_signal (fifo->notFull);
		printf ("consumer: recieved %d.\n", d);
		usleep (50000);
	}
	return (NULL);
}

#ifdef 0
typedef struct {
	int buf[QUEUESIZE];
	long head, tail;
	int full, empty;
	pthread_mutex_t *mut;
	pthread_cond_t *notFull, *notEmpty;
} queue;
#endif

queue *queueInit (void)
{
	queue *q;

	q = (queue *)malloc (sizeof (queue));
	if (q == NULL) return (NULL);

	q->empty = 1;
	q->full = 0;
	q->head = 0;
	q->tail = 0;
	q->mut = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t));
	pthread_mutex_init (q->mut, NULL);
	q->notFull = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
	pthread_cond_init (q->notFull, NULL);
	q->notEmpty = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
	pthread_cond_init (q->notEmpty, NULL);
	
	return (q);
}

void queueDelete (queue *q)
{
	pthread_mutex_destroy (q->mut);
	free (q->mut);	
	pthread_cond_destroy (q->notFull);
	free (q->notFull);
	pthread_cond_destroy (q->notEmpty);
	free (q->notEmpty);
	free (q);
}

void queueAdd (queue *q, int in)
{
	q->buf[q->tail] = in;
	q->tail++;
	if (q->tail == QUEUESIZE)
		q->tail = 0;
	if (q->tail == q->head)
		q->full = 1;
	q->empty = 0;

	return;
}

void queueDel (queue *q, int *out)
{
	*out = q->buf[q->head];

	q->head++;
	if (q->head == QUEUESIZE)
		q->head = 0;
	if (q->head == q->tail)
		q->empty = 1;
	q->full = 0;

	return;
}
在多线程编程中,生产者-消费者问题是一个经典的同步问题,它描述了多个线程之间如何共享一个固定大小的缓冲区的情况。生产者线程负责向缓冲区添加数据,而消费者线程则从缓冲区中取出数据。为了确保线程安全,需要使用适当的同步机制来防止数据竞争和死锁。 下面是一个使用Java语言实现的简单生产者-消费者问题的例子,其中使用了`wait()`和`notify()`方法来进行线程间的同步: ```java public class ProducerConsumer { private final int[] buffer; private int count = 0; // Number of elements in the buffer private final Object lock = new Object(); // Lock object for synchronization public ProducerConsumer(int size) { buffer = new int[size]; } class Producer implements Runnable { @Override public void run() { try { while (true) { produce(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } private void produce() throws InterruptedException { synchronized (lock) { while (count == buffer.length) { // Buffer is full, wait until consumer consumes some item lock.wait(); } // Produce an item and put it into the buffer int item = (int) (Math.random() * 100); buffer[count++] = item; System.out.println("Produced: " + item); // Notify the consumer that an item is available lock.notifyAll(); } } } class Consumer implements Runnable { @Override public void run() { try { while (true) { consume(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } private void consume() throws InterruptedException { synchronized (lock) { while (count == 0) { // Buffer is empty, wait until producer produces some item lock.wait(); } // Consume an item from the buffer int item = buffer[--count]; System.out.println("Consumed: " + item); // Notify the producer that space is available lock.notifyAll(); } } } public static void main(String[] args) { ProducerConsumer pc = new ProducerConsumer(10); // Create a buffer of size 10 new Thread(pc.new Producer()).start(); // Start producer thread new Thread(pc.new Consumer()).start(); // Start consumer thread } } ``` 在这个例子中,我们定义了一个`ProducerConsumer`类,它包含一个固定大小的缓冲区和一个用于同步的锁对象。生产者消费者分别是在两个独立的线程中运行的内部类。当缓冲区满时,生产者线程会等待,直到消费者线程消费了一些数据;同样,当缓冲区空时,消费者线程会等待,直到生产者线程生产了一些数据。通过这种方式,我们可以保证生产者消费者线程之间的正确同步。 请注意,在实际应用中,可能还需要考虑更多的细节,例如异常处理、线程中断以及更复杂的缓冲区管理等。此外,现代Java提供了更高层次的并发工具,如`java.util.concurrent`包中的`BlockingQueue`接口,它可以简化生产者-消费者实现[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值