IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c语言_多线程入门_信号量Semaphore -> 正文阅读

[C++知识库]c语言_多线程入门_信号量Semaphore

也属于线程同步的一种方式

信号量 Semaphore

定义:

有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。

目的:

类似计数器,常用在多线程同步任务上,信号量可以在当前线程某个任务完成后,通知别的线程,再进行别的任务。

分类:

  • 二值信号量:信号量的值只有 0 和 1,这和互斥量很类似,若资源被锁住,信号量的值为 0,若资源可用,则信号量的值为 1;
  • 计数信号量:信号量的值在 0 到一个大于 1 的限制值之间,该计数表示可用的资源的个数。

信号量在创建时需要设置一个初始值,表示同时可以有几个任务可以访问该信号量保护的共享资源,初始值为 1 就变成互斥锁 Mutex,即同时只能有一个任务可以访问信号量保护的共享资源

函数使用


首先需要 include <semaphore.h> 这个库,没啥好说的,除非你自己实现内部函数。和互斥锁一样也是四大金刚。
sem_init
简述:_创建信号量_
第一个参数:指向的信号对象
第二个参数:控制信号量的类型,如果其值为 0,就表示信号量是当前进程的局部信号量,否则信号量就可以在多个进程间共享
第三个参数:信号量 sem 的初始值
返回值:success 为 0,failure 为 - 1

 
int sem_init(sem_t *sem, int pshared, unsigned int value);

sem_post
简述:信号量的值加 1
第一个参数:信号量对象
返回值:success 为 0,failure 为 - 1

 
int sem_post(sem_t *sem);

sem_wait
简述:信号量的值加 - 1
第一个参数:信号量对象
返回值:success 为 0,failure 为 - 1

 
int sem_wait(sem_t *sem);

sem_destroy
简述:用完记得销毁哦~
第一个参数:信号量对象
返回值:success 为 0,failure 为 - 1

 
int sem_destroy(sem_t *sem);

举例

说明:你可以进行三个下载任务,但是最多选择同时执行二个(创建两个线程)。直接看 main 函数即可,信号量的逻辑都在里面,在实际代码中最好,所有的线程和信号量的创建、释放都要进行校验,这里为了方便阅读,减少代码行数,就不进行校验了。

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <windows.h>
 
#define MAXNUM 2
sem_t semDownload;
pthread_t a_thread, b_thread, c_thread;
int g_phreadNum = 1;
 
void InputInfo(void)
{
    printf("****************************************\n");
    printf("*** which task you want to download? ***\n");
    printf("*** you can enter [1-3],[0] is done  ***\n");
    printf("****************************************\n");
}
void *func1(void *arg)
{
    //等待信号量的值>0
    sem_wait(&semDownload);
    printf("==============  Downloading Task 1  ============== \n");
    Sleep(5000);
    printf("==============    Finished Task 1   ============== \n");
    g_phreadNum--;
    //等待线程结束 
    pthread_join(a_thread, NULL);
}
 
void *func2(void *arg)
{
    sem_wait(&semDownload);
    printf("==============  Downloading Task 2  ============== \n");
    Sleep(3000);
    printf("==============    Finished Task 2   ============== \n");
    g_phreadNum--;
    pthread_join(b_thread, NULL);
}
 
void *func3(void *arg)
{
    sem_wait(&semDownload);
    printf("==============  Downloading Task 3  ============== \n");
    Sleep(1000);
    printf("==============    Finished Task 3   ============== \n");
    g_phreadNum--;
    pthread_join(c_thread, NULL);
}
 
int main()
{
    int taskNum;
    InputInfo();
 
    while (scanf("%d", &taskNum) != EOF) {
        //输入0,判断是否正常退出
        if (taskNum == 0 && g_phreadNum <= 1) {
            break;
        }
        if (taskNum == 0){
            printf("Can not quit, casue count of threads is [%d]\n", g_phreadNum - 1);
        }
                //初始化信号量
        sem_init(&semDownload, 0, 0);
        printf("your choose Downloading Task [%d]\n", taskNum);
        //线程数超过2个则不下载
        if (g_phreadNum > MAXNUM) {
            printf("!!! You've reached a limit on the number of threads !!!\n");
            continue;
        }
        //用户选择下载Task
        switch (taskNum)
        {
        case 1:
            //创建线程1
            pthread_create(&a_thread, NULL, func1, NULL);
            //信号量+1,进而触发fun1的任务
            sem_post(&semDownload);
            //总线程数+1
            g_phreadNum++;
            break;
        case 2:
            pthread_create(&b_thread, NULL, func2, NULL);
            sem_post(&semDownload);
            g_phreadNum++;
            break;
        case 3:
            pthread_create(&c_thread, NULL, func3, NULL);
            sem_post(&semDownload);
            g_phreadNum++;
            break;
        default:
            printf("!!! eroor task [%d]  !!!\n", taskNum);
            break;
        }
 
    }
 
    //销毁信号量
    sem_destroy(&semDownload);
    return 0;
}

图解

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-02 14:26:18  更:2021-10-02 14:29:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:27:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码