用信号量解决生产者消费者问题
实验目的
通过实验,掌握Windows和Linux环境下互斥锁和信号量的实现 方法,加深对临界区问题和进程同步机制的理解,同时熟悉利用Windows API和Pthread API进行多线程编程的方法。
实验内容
1. 在Windows操作系统上,利用Win32 API提供的信号量机制,编写应 用程序实现生产者——消费者问题。
2. 在Linux操作系统上,利用Pthread API提供的信号量机制,编写应用程序实现生产者——消费者问题。
3. 两种环境下,生产者和消费者均作为独立线程,并通过empty、full、mutex三个信号量实现对缓冲进行插入与删除。
4. 通过打印缓冲区中的内容至屏幕,来验证应用程序的正确性。
实验步骤及运行结果和数据说明
(a)windows下用win32API实现
1.windows下建立多线程,分别表示生产者和消费者,首先引用
分别用来建立线程和引用windows下的函数
创建两个线程,分别用来表示生产者和消费者。
线程的表示函数 consumer和produce
main函数的实现
建立线程并关闭线程
变量的声明
声明三个信号量emp,full,mutex初值分别为20,0,1
生产者消费者的实现
生产者:
做20次循环,每次生产一个,同时empty-1,full+1,mutex保持每次生产的互斥。
消费者:
同样也是20个消费者,但只有full>1时才能进行。
实验运行结果
(b)linux下用pthread实现
1.首先是linux下多线程的创建,需要引用pthread.h
同时创建函数为 pthread_creat()
我们创建了生产者和消费者两个线程,名字分别为cunsumer和producer
2. 信号量的声明
在这里,互斥信号量the_mutex用pthread_mutex_t创建,同步信号量 用sem_t创建
信号量的初始:
3. 生产者和消费者函数的具体实现
生产者:
Sem_wait进行信号量的减一操作,sem_post进行信号量的加一操作
Pthread_mutex_lock则相应的对互斥信号量进行操作
消费者:
与生产者类似,不过每次消费时,必须先判断full>0,只有大于0时才能消费
Main()函数的实现
实验运行结果:
实验体会
做完这两个实验让我感觉windows和linux下的操作包括函数真的很不同,做这个实验首先要知道在不同的环境下线程,信号量是如何创建的,特别是windows下,函数名和函数的参数都十分复杂,这就需要我们了解一下每个参数的作用,然后才能更好的运用,但实验的整体思路是一样的,都是生产者和消费者问题,因此实验的思路还是很清晰的。
源程序
Windows:
#include
#include
#include
using namespace std;
HANDLE emp =CreateSemaphore(NULL, 20, 1, NULL); //创建同步信号量emp
HANDLE full =CreateSemaphore(NULL, 0, 1, NULL); //创建同步信号量full
HANDLE mutex =CreateSemaphore(NULL, 1, 1, NULL);//创建互斥信号量mutex
DWORD WINAPI consumer(PVOID pvPram);
DWORD WINAPI produce(PVOID pvPram);
int main()
{
//创建生产者和消费者线程
HANDLE pro = CreateThread(NULL, 0, produce,NULL, 0,NULL);
HANDLE con = CreateThread(NULL, 0, consumer,NULL, 0,NULL);
//关闭线程
CloseHandle(pro);
CloseHandle(con);
system("pause");
return 0;
}
//生产者函数实现
DWORD WINAPI produce(PVOID pvPram)
{
for(int i=1;i<=20;i++)
{
WaitForSingleObject(emp,INFINITE);//emp-1
WaitForSingleObject(mutex,INFINITE);//保证每次操作的互斥
cout<< "第" << i<< "个生产者" << endl;
ReleaseSemaphore(mutex, 1, NULL);
ReleaseSemaphore(full, 1, NULL);//full+1
}
return 0;
}
DWORD WINAPI consumer(PVOID pvPram)
{
for(int i=1;i<=20;i++)
{
WaitForSingleObject(full,INFINITE);//当fulll>0时才可以消费
WaitForSingleObject(mutex,INFINITE);//互斥
cout<< "第" << i<< "个消费者" << endl;
ReleaseSemaphore(mutex, 1, NULL);
ReleaseSemaphore(emp, 1, NULL);
}
return 0;
}
Linux:
#include
#include
#include
#include
#include
#include
pthread_mutex_t the_mutex;
sem_t empty;
sem_t full;
int buffer = 0;
void producer(void )
{
int i;
for(i=1; i<=20;i++)
{
sem_wait(&empty);
pthread_mutex_lock(&the_mutex);
printf("procucer produce %d\n",i);
pthread_mutex_unlock(&the_mutex);
sem_post(&full);
sleep(1);
}
}
void consumer(void )
{
int i;
for(i=1;i<=20;i++)
{
sem_wait(&full);
pthread_mutex_lock(&the_mutex);
printf("constumer consum %d\n",i);
pthread_mutex_unlock(&the_mutex);
sem_post(&empty);
sleep(1);
}
}
int main(int argc, char *argv[])
{
pthread_t pro, con;
pthread_mutex_init(&the_mutex, 0);
sem_init(&full,0,0);
sem_init(&empty,0,20);
pthread_create(&con, 0,(void *) consumer, 0);
pthread_create(&pro, 0,(void *) producer, 0);
pthread_join(pro,0);
pthread_join(con,0);
pthread_mutex_destroy(&the_mutex);
return 0;
}