1. 环形队列
在队列为空时,生产者必须先运行,消费者不能越过生产者
在队列为满时,消费者先运行,生产者不能超过消费者一圈,
不能同时访问同一位置:
2. 信号量
sem_t sem;//POSIX的线程标准下的
信号量机制通过信号量的值控制可用资源的数量。线程访问共享资源前,需要申请获取一个信号量,如果信号量为0,说明当前无可用的资源,线程无法获取信号量,则该线程会等待其他资源释放信号量(信号量加1)。如果信号量不为0,说明当前有可用的资源,此时线程占用一个资源,对应信号量减1。
举例:
停车场有5个停车位,汽车可使用停车位。在这里5个停车位是共享的资源,汽车是线程。开始信号量为5,表明此时有5个停车位可用。一辆汽车进入停车场前,先查询信号量的值,不为0表明有可用停车位,汽车进入停车场并使用一个停车位,信号量减1,表明占用一个停车位,可用数减少。
信号量初始化函数:
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem: 信号量
pshared:参数表示这个信号量是否在进程的线程之间共享进程之间
value:初始值
nt sem_wait(sem_t *sem);
该函数申请一个信号量,当前无可用信号量则等待,有可用信号量时占用一个信号量,对信号量的值减1。
信号量加1:
int sem_post(sem_t *sem);
该函数释放一个信号量,信号量的值加1。
销毁信号量:
int sem_destory(sem_t *sem);
该函数销毁信号量。
sem_init(&blankSem, 0, SIZE);//初始化
sem_init(&dataSem, 0, 0);
3.临界资源
创建全局数组 int ring[SIZE] = 0;
这样信号量不仅可以实现生产者与消费者的同步
,而且可以实现互斥
(两者不可能同时访问同一资源);
1. 基于环形队列的单生产者单消费者模型
void* product(void *arg)//生产者
{
int i = 0;
int n = 0;
while(1)
{
sem_wait(&blankSem);//申请格子放数据
ring[i] = n++;//减一成功后,放数据
sem_post(&dataSem);//数据放完成后,数据数目加1,
printf("product doing! %d\n",ring[i++]);
i = i%SIZE;
}
return NULL;
}
void* consume(void *arg) //消费者
{
int i = 0;
int data = 0;
while(1)
{ sem_wait(&dataSem);//请求拿数据,阻塞方式
data = ring[i]; //
sem_post(&blankSem);//拿到数据后,空格加1
printf("consume doing %d\n",data);
sleep(1);
i++;
i = i%SIZE;//实现环形
}
}
2. 基于环形队列的多生产者多消费者
模型编写。
信号量只能实现生产者与消费者之间的·互斥·同步·
现在多生产者和消费者,所以需要加入,互斥锁实现生产者与生产者之间的互斥,消费者与消费者之间的互斥;
int i = 0;
int n = 0;
int data = 0;
void* product_1(void *arg)//生产者1
{
while(1)
{
pthread_mutex_lock(&lock_2);
//信号量在生产者之间是临界资源,所以在互斥锁加解之间
sem_wait(&blankSem);//申请放数据
ring[i] = n++;
sem_post(&dataSem);//放完数据,增加数据数目
printf("product_1 doing! %d\n",ring[i++]);
i = i%SIZE;
pthread_mutex_unlock(&lock_2);//解锁
sleep(1);
}
return NULL;
}
void* product_2(void *arg)//生产者2
{
while(1)
{
pthread_mutex_lock(&lock_2);//解锁
sem_wait(&blankSem);
ring[i] = n++;
sem_post(&dataSem);
printf("product_2 doing! %d\n",ring[i++]);
i = i%SIZE;
pthread_mutex_unlock(&lock_2);
sleep(1);
}
return NULL;
}
void* consume_1(void *arg)//消费者1
{
int data = 0;
while(1)
{
pthread_mutex_lock(&lock_1);//解锁
sem_wait(&dataSem);//申请拿数据
data = ring[con];
sem_post(&blankSem);//拿数据后,增加空格数目
printf("consume_1 doing %d\n",data);
sleep(1);
con++;
con = con%SIZE;
pthread_mutex_unlock(&lock_1);//解锁
sleep(2);
}
return NULL;
}
void* consume_2(void *arg)//消费者2
{
int data = 0;
while(1)
{
pthread_mutex_lock(&lock_1);
sem_wait(&dataSem);
data = ring[con];
sem_post(&blankSem);
printf("consume_2 doing %d\n",data);
sleep(1);
con++;
con = con%SIZE;
pthread_mutex_unlock(&lock_1);
sleep(2);
}
return NULL;
}