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 文件夹


  • 相关阅读:
    「UVA12293」 Box Game
    「CF803C」 Maximal GCD
    「CF525D」Arthur and Walls
    「CF442C」 Artem and Array
    LeetCode lcci 16.03 交点
    LeetCode 1305 两棵二叉搜索树中的所有元素
    LeetCode 1040 移动石子直到连续 II
    LeetCode 664 奇怪的打印机
    iOS UIPageViewController系统方法崩溃修复
    LeetCode 334 递增的三元子序列
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7147033.html
Copyright © 2011-2022 走看看