zoukankan      html  css  js  c++  java
  • linux系统编程:线程同步-信号量(semaphore)

                                 线程同步-信号量(semaphore)

    生产者与消费者问题再思考

    在实际生活中,仅仅要有商品。消费者就能够消费,这没问题。

    但生产者的生产并非无限的。比如,仓库是有限的,原材料是有限的,生产指标受消费指标限制等等。为了进一步,解决好生产者与消费者问题,引入信号量进机制。


    信号量

    信号量(semaphore)是相互排斥量的升级版:相互排斥量的状态为0或1。而信号量能够为n。

    也就是说,使用相互排斥量时。最多同意一个线程进入关键区,而信号量同意多个,详细值是信号量当前的内部值。


    相关函数

    sem_t       //信号量类型
    sem_init(sem_t *sem, int pshared, unsigned int value);
    sem_wait(sem_t *sem)
    sem_trywait
    sem_timedwait
    sem_post(sem_t *sem)
    sem_destroy
    重要的是理解:sem_wait和sem_post两个函数。

    sem_wait(sem);当sem为零时,线程堵塞。否则,sem减一,线程不堵塞。

    sem_post(sem);sem加一。

    此外,使用sem_init方法,对信号量类型初始化,第二个參数。默认是0,标明用于线程之间。第三个參数指定了初始值。


    单生产者与单消费者

    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <semaphore.h>
    #define NUM 5
    sem_t blank_num, product_num;
    int i, j, k;
    int goods[NUM];
    void *producer(void *argv)
    {
    	while (1)
    	{
    		sem_wait(&blank_num);
    		goods[i] = rand() % 100 + 1;
    		printf("produce %d
    ", goods[i]);
    		sem_post(&product_num);
    		i = (i + 1) % NUM;
    		sleep(rand() % 2);
    	}
    }
    void *comsumer(void *argv)
    {
    	while (1)
    	{
    		sem_wait(&product_num);
    		printf("comsume %d
    ", goods[j]);
    		goods[j] = 0;
    		sem_post(&blank_num);
    		j = (j + 1) % NUM;
    		sleep(rand() % 2);
    	}
    }
    int main(void)
    {
    	i = j = k = 0;
    	//初始化信号量
    	sem_init(&blank_num, 0, NUM);
    	sem_init(&product_num, 0, 0);
    	pthread_t pro, com;
    	pthread_create(&com, NULL, producer, NULL);
    	pthread_create(&pro, NULL, comsumer, NULL);
    	pthread_join(com, NULL);
    	pthread_join(pro, NULL);
    	sem_destroy(&blank_num);
    	sem_destroy(&product_num);
    	return 0;
    }


    多生产者与多消费者

    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <semaphore.h>
    #define NUM 5
    pthread_mutex_t m1, m2;
    sem_t blank_num, product_num;
    int goods[NUM];
    int i, j, k;
    void *producer(void *argv)
    {
    	while (1)
    	{
    		sem_wait(&blank_num);
    		pthread_mutex_lock(&m1);
    		goods[i] = rand() % 100 + 1;
    		printf("produce %d
    ", goods[i]);
    		i = (i + 1) % NUM;
    		pthread_mutex_unlock(&m1);
    		sem_post(&product_num);
    		sleep(rand() % 2);
    	}
    }
    void *comsumer(void *argv)
    {
    	while (1)
    	{
    		sem_wait(&product_num);
    		pthread_mutex_lock(&m2);
    		printf("comsume %d
    ", goods[j]);
    		goods[j] = 0;   //置零
    		j = (j + 1) % NUM;
    		pthread_mutex_unlock(&m2);
    		sem_post(&blank_num);
    		sleep(rand() % 2);
    	}
    }
    int main(void)
    {
    	i = j = k = 0;
    	//初始化信号量及相互排斥量
    	sem_init(&blank_num, 0, NUM);
    	sem_init(&product_num, 0, 0);
    	pthread_mutex_init(&m1, NULL);
    	pthread_mutex_init(&m2, NULL);
    	pthread_t pro[2], com[3];
    	for (k = 0; k < 3; k++)
    		pthread_create(&com[k], NULL, producer, NULL);
    	for (k = 0; k < 2; k++)
    		pthread_create(&pro[k], NULL, comsumer, NULL);
    	for (k = 0; k < 3; k++)
    		pthread_join(com[k], NULL);
    	for (k = 0; k < 2; k++)
    		pthread_join(pro[k], NULL);
    	pthread_mutex_destroy(&m1);
    	pthread_mutex_destroy(&m2);
    	sem_destroy(&blank_num);
    	sem_destroy(&product_num);
    	return 0;
    }


         

    CCPP Blog 文件夹


  • 相关阅读:
    网络并发服务器设计
    linux脚本编程技术
    守护进程学习
    UDP通讯程序设计
    TCP通讯程序设计
    linux中socket的理解
    linux网络协议
    kafka ProducerConfig 配置
    crontab定时执行datax
    crontab
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7147033.html
Copyright © 2011-2022 走看看