0
点赞
收藏
分享

微信扫一扫

linux生产者消费者(使用信号量)

信号量:

应用于线程、进程间同步。
相当于 初始化值为 N 的互斥量。  N值,表示可用资源数, 可以同时访问共享数据区的线程数。
函数:
	sem_t sem;	定义类型。
	int sem_init(sem_t *sem, int pshared, unsigned int value);

	参数:
		sem: 信号量 
		pshared:	0: 用于线程间同步
			1: 用于进程间同步
		value:N值。(表示可用资源数)

	sem_destroy();
	sem_wait();		一次调用,做一次-- 操作, 当信号量的值为 0 时,再次 -- 就会阻塞。 (对比 pthread_mutex_lock)
	sem_post();		一次调用,做一次++ 操作. 当信号量的值为 N 时, 再次 ++ 就会阻塞。(对比 pthread_mutex_unlock)

使用mutex(互斥量、互斥锁)一般步骤:
pthread_mutex_t 类型。

1. pthread_mutex_t lock;  创建锁
2  pthread_mutex_init; 初始化		1
3. pthread_mutex_lock;加锁		1--	--> 0
4. 访问共享数据(stdout)		
5. pthrad_mutext_unlock();解锁		0++	--> 1
6. pthead_mutex_destroy;销毁锁

初始化互斥量:
	pthread_mutex_t mutex;
	1. pthread_mutex_init(&mutex, NULL);   			动态初始化。
	2. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;	静态初始化。
注意事项:
	尽量保证锁的粒度, 越小越好。(访问共享数据前,加锁。访问结束【立即】解锁。)
	互斥锁,本质是结构体。 我们可以看成整数。 初值为 1。(pthread_mutex_init() 函数调用成功。)
	加锁: --操作, 阻塞线程。
	解锁: ++操作, 换醒阻塞在锁上的线程。
	try锁:尝试加锁,成功--。失败,返回。同时设置错误号 EBUSY
/*信号量实现 生产者 消费者问题*/

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

#define NUM 5               

int queue[NUM];                                     //全局数组实现环形队列
sem_t blank_number, product_number;                 //空格子信号量, 产品信号量

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;


void *producer(void *arg)
{
    int i = 0;

    while (1) {
        sem_wait(&blank_number);                    //生产者将空格子数--,为0则阻塞等待
        queue[i] = rand() % 1000 + 1;               //生产一个产品
        printf("----Produce---%d\n", queue[i]);        
        
	sem_post(&product_number);                  //将产品数++

        i = (i+1) % NUM;                            //借助下标实现环形
        sleep(rand()%1);
    }
}

void *consumer(void *arg)
{
    int i = 0;

    while (1) {
  

    sem_wait(&product_number);                  //消费者将产品数--,为0则阻塞等待

    printf("--Consume---%d, i = %d\n", queue[i], i);
    queue[i] = 0;                               //消费一个产品 
    i = (i+1) % NUM;

	printf("--------i = %d \n", i);
	sem_post(&blank_number);                    //消费掉以后,将空格子数++

    sleep(rand()%3);
    }
}

int main(int argc, char *argv[])
{
    pthread_t pid, cid, cid2;

    sem_init(&blank_number, 0, NUM);                //初始化空格子信号量为5, 线程间共享 -- 0
    sem_init(&product_number, 0, 0);                //产品数为0

    pthread_create(&pid, NULL, producer, NULL);
    pthread_create(&cid, NULL, consumer, NULL);
    pthread_create(&cid2, NULL, consumer, NULL);


    pthread_join(pid, NULL);
    pthread_join(cid, NULL);
    pthread_join(cid2, NULL);


    sem_destroy(&blank_number);
    sem_destroy(&product_number);
    
    pthread_mutex_destroy(&mutex1);

    pthread_mutex_destroy(&mutex2);

    return 0;
}

consumer的i是在栈空间的,属于线程单独的;应该使用全局变量才能同步,要不两个线程的 i 是两个不一样的。
在这里插入图片描述

/*信号量实现 生产者 消费者问题*/

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

#define NUM 5               

int queue[NUM];                                     //全局数组实现环形队列
sem_t blank_number, product_number;                 //空格子信号量, 产品信号量

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
int k = 0;
int i = 0;

void *producer(void *arg)
{

    while (1) {
		sem_wait(&blank_number);                    //生产者将空格子数--,为0则阻塞等待
		pthread_mutex_lock(&mutex1);

        queue[i] = rand() % 1000 + 1;               //生产一个产品
        printf("----Produce---%d\n", queue[i]);        
        
		pthread_mutex_unlock(&mutex1);
		sem_post(&product_number);                  //将产品数++

        i = (i+1) % NUM;                            //借助下标实现环形
        sleep(rand()%1);
    }
}

void *consumer(void *arg)
{

    while (1) {
 
    sem_wait(&product_number);                  //消费者将产品数--,为0则阻塞等待
	pthread_mutex_lock(&mutex1);

    printf("--Consume---%d, k = %d\n", queue[k], k);
    queue[k] = 0;                               //消费一个产品 
    k = (k+1) % NUM;
	printf("--------k = %d \n", k);

	pthread_mutex_unlock(&mutex1);
	sem_post(&blank_number);                    //消费掉以后,将空格子数++

   // sleep(rand()%3);
    }
}

int main(int argc, char *argv[])
{
    pthread_t pid, cid, cid2;

    sem_init(&blank_number, 0, NUM);                //初始化空格子信号量为5, 线程间共享 -- 0
    sem_init(&product_number, 0, 0);                //产品数为0

    pthread_create(&pid, NULL, producer, NULL);
	pthread_create(&pid, NULL, producer, NULL);
    pthread_create(&cid, NULL, consumer, NULL);
    pthread_create(&cid2, NULL, consumer, NULL);


    pthread_join(pid, NULL);
    pthread_join(cid, NULL);
    pthread_join(cid2, NULL);


    sem_destroy(&blank_number);
    sem_destroy(&product_number);
    
    pthread_mutex_destroy(&mutex1);

    pthread_mutex_destroy(&mutex2);

    return 0;
}

举报

相关推荐

0 条评论