1、描述一下生产者消费者模型。
有n个生产者线程生产产品,m个消费者线程消费产品。在这里他们需要互斥地访问产品。
2、为什么要把产品数量设入临界区,如何实现临界区的(如何调用相关API)?
因为如果在资源抢占过程中,恢复现场时会覆盖另一个线程对产品数量的操作结果。
在Linux下,调用pthread_mutex_lock(&mutex)和pthread_mutex_unlock(&mutex)对临界区加锁解锁。
3、在临界区内是如何避免死锁的。并请你深入操作系统内核层面剖析一下其中原理。
定义产品数量为g_num一个消费者进程进入临界区后
if(g_num == 0){丢弃锁}
线程通过调用pthread_cond_wait(&g_cond, &g_mutex)来进行丢弃锁。
在调用pthread_cond_wait()后,操作系统做了三件事情。
第一步线程丢锁,然后线程休眠,第三步线程等待苏醒。线程需要用另一个API来唤醒。thread_cond_signal()。
4、请编码实现生产者消费者模型。并将产品数量控制在20以内。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#define CUSTOMER_COUNT 2
#define PRODUCTER_COUNT 4
int g_num = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//定义锁
pthread_cond_t my_condition = PTHREAD_COND_INITIALIZER;//定义条件并初始化
void* customer(void* arg)//消费者线程
{
int inum = 0;
inum = *(int *)arg;
while (1)
{
pthread_mutex_lock(&mutex); //线程获得锁,进入临界区
printf("cumstomer:%d\n", inum);
while (g_num == 0)
{
printf("\nwaiting start\n");
pthread_cond_wait(&my_condition, &mutex);//条件锁
printf("waiting end\n");
}
printf("customer run\n");
g_num--;//消费产品
printf("customer end\n");
pthread_mutex_unlock(&mutex);//线程释放锁,退出临界区
sleep(1);
}
pthread_exit(0);
}
void* producter(void* arg)//生产者线程
{
int inum = 0;
inum = *(int *)arg;
while (1)
{
pthread_mutex_lock(&mutex);//线程获得锁,创建临界区,判断产品数量
if (g_num > 20)
{
printf("Product:%d too much.\n", g_num);
pthread_mutex_unlock(&mutex);
sleep(1);
continue;
}
else
{
pthread_mutex_unlock(&mutex);
}
pthread_mutex_lock(&mutex);//获得锁,进入临界区
printf("producter:%d\n", inum);
printf("The num of g_num:%d\n", g_num);
printf("producter run\n");
g_num++;//生产产品
printf("producter end\n");
pthread_cond_signal(&my_condition);//产出产品,唤醒等待线程
pthread_mutex_unlock(&mutex);//释放锁,退出临界区
sleep(1);
}
pthread_exit(0);
}
int main()
{
int i = 0;
pthread_t threadArray[CUSTOMER_COUNT + PRODUCTER_COUNT + 10];//线程数组
for (i = 0; i < PRODUCTER_COUNT; i++)//创建生产者线程
{
pthread_create(&threadArray[i], NULL, producter, (void*)&i);
}
for (i = 0; i < CUSTOMER_COUNT; i++)//创建消费者线程
{
pthread_create(&threadArray[i + CUSTOMER_COUNT], NULL, customer, (void*)&i);
}
for (i = 0; i < PRODUCTER_COUNT + CUSTOMER_COUNT; i++)//等待线程结束
{
pthread_join(threadArray[i], NULL);
}
return 0;
}