线程同步-信号量(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\n", 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\n", 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\n", 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\n", 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系统编程:线程同步-信号量(semaphore)的更多相关文章

  1. linux系统编程--线程同步

    同步概念 所谓同步,即同时起步,协调一致.不同的对象,对“同步”的理解方式略有不同. 如,设备同步,是指在两个设备之间规定一个共同的时间参考: 数据库同步,是指让两个或多个数据库内容保持一致,或者按需 ...

  2. Linux系统编程 —线程同步概念

    同步概念 同步,指对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化的现象. 但是,对于不同行业,对于同步的理解略有不同.比如:设备同步,是指在两个设备之间规定一个共同的时间参考:数据 ...

  3. 经典线程同步 信号量Semaphore

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  4. 秒杀多线程第八篇 经典线程同步 信号量Semaphore

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <且不超过最大资源数量. 第三个參数能够用来传出先前的资源计数,设为NULL表示不须要传出. 注意:当 ...

  5. 多线程面试题系列(8):经典线程同步 信号量Semaphore

    前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore常用有三个函数 ...

  6. 转---秒杀多线程第八篇 经典线程同步 信号量Semaphore

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  7. Linux系统编程——线程私有数据

    在多线程程序中.常常要用全局变量来实现多个函数间的数据共享.因为数据空间是共享的,因此全局变量也为全部线程共同拥有. 測试代码例如以下: #include <stdio.h> #inclu ...

  8. linux系统编程--线程

    安装线程man page,命令:sudo apt-get install manpages-posix-dev 线程概念 什么是线程 LWP:light weight process 轻量级的进程,本 ...

  9. 秒杀多线程第八篇 经典线程同步 信号量Semaphore (续)

    java semaphore实现: Semaphore当前在多线程环境下被扩放使用,操作系统的信号量是个很重要的概念,在进程控制方面都有应用.Java 并发库 的Semaphore 可以很轻松完成信号 ...

随机推荐

  1. android手机web网站拨打电话几种方式

    1. <input name="phone" format="*m" value="13"/> <do type=&quo ...

  2. CAD参数绘制块引用对象(网页版)

    主要用到函数说明: _DMxDrawX::DrawBlockReference 绘制块引用对象.详细说明如下: 参数 说明 DOUBLE dPosX 插入点的X坐标 DOUBLE dPosY 插入点的 ...

  3. vue项目打包步骤及运行打包项目

    (1)项目打包 终端运行命令 npm run build 打包成功的标志与项目的改变,如下图: 点击index.html,通过浏览器运行,出现以下报错,如图: 那么应该如何修改呢?    具体步骤如下 ...

  4. pycharm 破解

    亲测有效! http://blog.lanyus.com/archives/174.html 备注: 注册码破解链接:http://idea.lanyus.com/ 将下载的jar包放入PyCharm ...

  5. [Python3网络爬虫开发实战] 1.3.2-Beautiful Soup的安装

    Beautiful Soup是Python的一个HTML或XML的解析库,我们可以用它来方便地从网页中提取数据.它拥有强大的API和多样的解析方式,本节就来了解下它的安装方式. 1. 相关链接 官方文 ...

  6. nodejs学习(一) ---- nodejs + express应用生成器 快速创建应用

    1.node安装及环境配置(自行百度) 2.express安装及配置 (自行百度) 3.通过应用生成器工具 express 快速创建应用骨架   全局安装应用生成器 : npm install exp ...

  7. centos7搭建安装sentry

    Sentry 是一款基于 Django实现的错误日志收集和聚合的平台,它是 Python 实现的,但是其日志监控功能却不局限于python,对诸如 Node.js, php,ruby, C#,java ...

  8. 20Spring切面的优先级

    通过使用@order注解指定切面的优先级,值越小,优先级越高代码: package com.cn.spring.aop.impl; //加减乘除的接口类 public interface Arithm ...

  9. ecshop 修改支持php7 方案

    修改方法 http://jsb.php-php.com/2016/05/472/ 修改数据库配置 data/config.php

  10. Python之机器学习-波斯顿房价预测

    目录 波士顿房价预测 导入模块 获取数据 打印数据 特征选择 散点图矩阵 关联矩阵 训练模型 可视化 波士顿房价预测 导入模块 import pandas as pd import numpy as ...