#defineBUFFER_SIZE10//缓冲区的大小
typedefintbuffer_item;//定义缓冲区内的数据类型
buffer_itembuffer[BUFFER_SIZE];//缓冲区
intin,out;//对缓冲区操作的变量
pthread_mutex_tmutex;//信号量mutex提供了对缓冲池访问的互斥要求
sem_tempty,full;//信号量empty和full分别表示空缓冲顶和满缓冲顶的个数
intpro_speed,con_speed;//可以设定生产者的生产速度及消费者的消费速度
intinsert_item(buffer_itemitem)
{//将生产的产品放入缓冲区
buffer[in]=item;
printf("******insert缓冲池第%d号******\n",in);
inc(in);
}
intremove_item(buffer_item*item)
{//从缓冲区内移走一个产品
*item=buffer[out];
printf("******remove缓冲池第%d号******\n",out);
inc(out);
}
void*producer(void*param)
{//生产者进程
buffer_itemitem;
intnum=0;
while
(1)
{
sleep(rand()%(16-pro_speed));
printf("\n******第%d次生产******\n",++num);
printf("******等待empty信号******\n");
sem_wait(&empty);
printf("******等待解锁******\n");
pthread_mutex_lock(&mutex);
printf("******上锁,准备生产******\n");
item=rand()%1000+1;
printf("******生产产品%d*******\n",item);
insert_item(item);
printf("*******解锁******\n");
printf("******第%d次生产结束*******\n\n",num);
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
}
void*consumer(void*param)
{//消费者进程
buffer_itemitem;
intnum=0;
while
(1){
sleep(rand()%(16-con_speed));
printf("\n******第%d次消费*****\n",++num);
printf("******等待full信号******\n");
sem_wait(&full);
printf("******等待解锁******\n");
pthread_mutex_lock(&mutex);
printf("******上锁,准备消费******\n");
remove_item(&item);
pthread_mutex_unlock(&mutex);
sem_post(&empty);
printf("******消费产品%d*******\n",item);
printf("*******解锁******\n");
printf("******第%d次消费结束*******\n\n",num);
}
}
intmain()//主函数
{
pthread_ttid1,tid2;
pthread_attr_tattr1,attr2;
srand(time(NULL));
pthread_mutex_init(&mutex,NULL);//初始化
sem_init(&empty,0,BUFFER_SIZE);
sem_init(&full,0,0);
in=0;
out=0;
printf("***********************\n");
printf("********开始!
***********\n");
printf("***********************\n");
printf("生产者速度(1-15):
\n");
scanf("%d",&pro_speed);
printf("消费者速度(1-15):
\n");
scanf("%d",&con_speed);
pthread_attr_init(&attr1);
pthread_create(&tid1,&attr1,producer,NULL);
pthread_attr_init(&attr2);
pthread_create(&tid2,&attr2,consumer,NULL);
sleep(100);
printf("*******程序over*******\n");
return0;
}
【实验步骤】
编写程序代码geditsx.c,再对代码进行编译gccsx.c–osx–lpthread,编译无错误,进行运行./sx,根据提示要求进行填写生产者和消费速度,观察消费者和生产者进程。
【实验结果】
【实验体会】
1、Linux中生成线程方法:
第一种方式是用pthread库来实现的,是在用户程序本身中实现线程,这实际上是对线程的一种模拟,线程之间的切换和调度是在用户的进程内部进行的,这种方式就被称为用户空间的线程。
这种线程的好处是实现非常简单,性能也非常好,因为线程之间的切换都在用户进程内部进行,切换开销比较小。
缺点也非常明显,首先就是不能充分利用高端系统的SMP多处理器的优点,因为一个进程只能由一个处理器处理,第二点由于用户空间是在用户空间切换,某个线程遇到一个需要阻塞的系统调用进而就会造成这个进程被阻塞,因而所有线程被阻塞。
第二种方式是通过修改进程的实现方式来完成,可以使用不完全的进程创建方式创建共享数据空间的进程,在Linux下这种系统调用为clone()。
2、Ptrtead生成线程:
POSIXthread简称为pthread,Posix线程是POSIX标准线程该标准定义内部API创建和操纵线程。
数据类型pthread_t:
线程句柄pthread_attr_t:
线程属性线程操纵函数(省略参数):
pthread_create():
创建一个线程
pthread_exit():
终止当前线程
pthread_cancel():
中断另外一个线程的运行
pthread_join():
阻塞当前的线程,直到另外一个线程运行结束
pthread_attr_init():
初始化线程的属性
pthread_attr_setdetachstate():
设置脱离状态的属性(决定这个线程在终止时是否可以被结合)
pthread_attr_getdetachstate():
获取脱离状态的属性
pthread_attr_destroy():
删除线程的属性
pthread_kill():
向线程发送一个信号