信号量实现线程同步代码

news2024/11/27 0:45:15

信号量&实现线程同步代码

  • 信号量
  • 线程同步
  • 示例代码

信号量

信号量(Semaphore)是一种用于多线程编程中的同步工具,用于管理对共享资源的访问。它可以控制同时访问某个资源的线程数量,并提供了对共享资源的互斥访问。
在这里插入图片描述

信号量通常用于解决线程间的互斥和同步问题,其中包括以下两种类型的信号量:

  1. 二进制信号量(Binary Semaphore):也称为互斥信号量(Mutex Semaphore),它只有两种状态:0和1。它用于实现临界区的互斥访问,即同一时间只允许一个线程访问共享资源。典型的例子是互斥锁(Mutex)。

  2. 计数信号量(Counting Semaphore):也称为一般信号量(General Semaphore),它可以有多个状态值。它用于控制多个线程对共享资源的访问数量,可以限制同时访问某个资源的线程数目。典型的例子是生产者-消费者问题中的缓冲区。

常见的信号量操作包括:

  • sem_init:初始化信号量,设置初始值。
  • sem_wait:等待信号量,如果信号量值大于0,则将信号量值减1,继续执行;否则线程阻塞等待。
  • sem_post:释放信号量,将信号量值加1,唤醒等待的线程。
  • sem_destroy:销毁信号量,释放相关资源。

需要注意的是,信号量不仅限于线程间的同步,还可以用于进程间的同步。在多进程编程中,可以使用命名信号量(Named Semaphore)来实现不同进程之间的同步与互斥。

信号量提供了一种有效的方式来协调并发线程对共享资源的访问,避免竞态条件和数据不一致性问题。它是多线程编程中重要的同步机制之一。

线程同步

线程同步是指多个线程之间协调和管理共享资源的访问,以确保线程安全和数据一致性。在线程并发执行时,如果多个线程同时访问共享资源,可能会导致竞态条件(Race Condition)和数据不一致的问题。因此,需要使用适当的同步机制来保证线程间的正确协作。

下面介绍几种常见的线程同步机制:

  1. 互斥锁(Mutex):互斥锁是一种二进制信号量,用于实现对临界区(Critical Section)的互斥访问。一次只允许一个线程进入临界区,其他线程需要等待。常用的函数有pthread_mutex_init(初始化互斥锁)、pthread_mutex_lock(获取互斥锁)、pthread_mutex_unlock(释放互斥锁)、pthread_mutex_destroy(销毁互斥锁)。

  2. 条件变量(Condition Variable):条件变量用于线程间的等待和唤醒机制。它允许线程在某个条件满足时等待,而不是忙等待。常用的函数有pthread_cond_init(初始化条件变量)、pthread_cond_wait(等待条件变量满足)、pthread_cond_signal(唤醒等待线程)、pthread_cond_broadcast(广播唤醒所有等待线程)、pthread_cond_destroy(销毁条件变量)。

  3. 信号量(Semaphore):信号量是一种计数信号量,用于控制多个线程对共享资源的访问数量。它可以限制同时访问某个资源的线程数目。常用的函数有sem_init(初始化信号量)、sem_wait(等待信号量)、sem_post(释放信号量)、sem_destroy(销毁信号量)。

  4. 屏障(Barrier):屏障用于同步多个线程,在达到指定数量的线程之前,线程将被阻塞,等待其他线程到达。当所有线程都到达屏障点后,它们将同时继续执行。常用的函数有pthread_barrier_init(初始化屏障)、pthread_barrier_wait(等待屏障)、pthread_barrier_destroy(销毁屏障)。

这些同步机制可以根据具体需求选择和组合使用,以确保线程安全和数据一致性。线程同步的正确实现可以避免竞态条件和数据不一致性问题,确保多线程程序的正确性。

示例代码

下面是一个使用C语言编写的信号量实现线程同步的示例代码:

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

#define NUM_THREADS 3

sem_t semaphore;

void* thread_function(void* thread_id) {
    int id = *(int*)thread_id;
    
    printf("Thread %d: Waiting for semaphore...\n", id);
    sem_wait(&semaphore); // 等待信号量
    
    printf("Thread %d: Semaphore acquired.\n", id);
    
    // 执行一些需要同步的操作
    
    printf("Thread %d: Releasing semaphore.\n", id);
    sem_post(&semaphore); // 释放信号量
    
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[NUM_THREADS];
    int thread_ids[NUM_THREADS];

    // 初始化信号量
    if (sem_init(&semaphore, 0, 1) == -1) {
        perror("Semaphore initialization failed");
        exit(EXIT_FAILURE);
    }
    
    // 创建线程
    for (int i = 0; i < NUM_THREADS; i++) {
        thread_ids[i] = i;
        if (pthread_create(&threads[i], NULL, thread_function, &thread_ids[i]) != 0) {
            perror("Thread creation failed");
            exit(EXIT_FAILURE);
        }
    }
    
    // 等待线程结束
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    
    // 销毁信号量
    sem_destroy(&semaphore);

    return 0;
}

在这个示例中,我使用了pthread库和semaphore信号量来实现线程同步。semaphore是一个信号量变量,通过sem_init函数进行初始化,并设置初始值为1。

每个线程通过调用sem_wait函数等待信号量。如果信号量的值大于0,则线程将继续执行;否则,线程将阻塞,直到信号量的值变为大于0为止。

在需要同步的操作执行完毕后,线程调用sem_post函数释放信号量,将信号量的值加1,允许其他线程继续执行。

主函数中创建了多个线程,并等待它们执行完毕。最后,通过sem_destroy函数销毁信号量。

注意:在实际应用中,可能需要更复杂的线程同步机制和更详细的错误处理。此示例仅用于演示基本的信号量使用方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/651166.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一个支持WinForms换肤的开源组件

博主介绍&#xff1a; &#x1f308;一个10年开发经验.Net老程序员&#xff0c;微软MVP、博客专家、CSDN/阿里云 .Net领域优质创作者&#xff0c;专注于.Net领域知识、开源项目分享&#xff01;&#x1f308; &#x1f6d5;文末获取&#xff0c;加入交流群&#x1f6d5; &#…

java数组(Array)

文章目录 一维数组的使用数组的长度数组元素的引用一维数组的遍历一维数组内存分析 数组元素的默认值多维数组的使用静态初始化动态初始化数组的长度和角标二维数组的遍历内存解析 Arrays工具类的使用 一维数组的使用 int[] arr; int arr1[]; double[] arr2; String[] arr3; …

网工内推 | 1-3年经验,思科、华为、华三厂商认证均可

01 地球村股份有限公司 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1、提供技术支持服务&#xff0c;提供设备的告警信息的分析处理及与故障问题定位服务&#xff1b; 2、及时响应在服务时限内完成处理设备故障&#xff0c;包括用户有线无线接入故障、系统故障处理…

数据库第四章(数据库安全性)

1.数据库安全性概述 disiz行 不安全因素&#xff1a; 1.非授权的用户对数据的恶意存取和破坏 2.数据库重要信息泄露 3.数据库环境的脆弱性 如何实现安全控制&#xff1f; 1.用户身份鉴别 口令鉴别 生物鉴别 2.存取控制 3.自主存取控制方法 4.授权与收回 grant and revok…

Map容器(Java)

文章目录 1.容器介绍1.1 容器接口结构1.2 简单解析 2. 容器创建(Member functions)3. 访问操作(Element access)3.1 keySet()3.2 entrySet() 4. 修改操作(Modifiers)4.1 put()4.2 remove()4.3 clear() 5. 容量操作(Member functions)5.1 size()5.2 isEmpety() 6. 其他操作(Othe…

用Swagger生成接口,pom中少了一个library参数,排查了几个小时

前言&#xff1a; 我们一般都会使用swagger生成restful接口&#xff0c;这样可以省不少时间&#xff0c;将更多的精力专注于写业务上。但接口也不是经常写&#xff0c;所以&#xff0c;swagger用的也不熟练。尤其是我喜欢拿之前的接口copy一份&#xff0c;然后在此基础上进行修…

1、springcloud环境搭建

目录 1、创建一个父项目 ​编辑 2、创建子项目 2.1创建订单系统-order ​编辑 2.2创建库存系统-stock 3、创建rest服务 3.1添加web依赖 3.2编写controller 3.3订单中需要调用库存中的扣减库存的接口 通过idea开发工具进行搭建 1、创建一个父项目 通过spring initializr…

QT day4 (time/tcp/draw)

如图所示设计一个闹钟 1、头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QColor> #include <QDebug> #include <QMessageBox> #include <QTimer> //定时器类的头文件 #include <QTime> …

搞定剑桥面试数学题番外篇2:使用多线程并发“加强版”

0. 概览 我们在之前三篇博文中已经介绍了如何用多种语言&#xff08;ruby、swift、c、x64 汇编和 ARM64 汇编&#xff09;实现一道“超超超难”的剑桥数学面试题&#xff1a; 有趣的小实验&#xff1a;四种语言搞定“超超超难”剑桥面试数学题 搞定“超超超难”剑桥面试数学…

【每日挠头算法题(7)】对称的二叉树|二叉树的所有路径

欢迎&#xff01; 前言一、对称的二叉树思路&#xff1a;递归法具体代码如下&#xff1a; 二、二叉树的所有路径思路&#xff1a;递归法具体代码如下&#xff1a; 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;随着人工智能的不…

如何快速选择合适的会计软件?这些推荐值得尝试!

现今&#xff0c;许多公司都在使用会计软件来管理它们的财务&#xff0c;提高工作效率。因此选择一个适合自己公司的会计软件是相当重要的。但是&#xff0c;对于许多小型企业而言&#xff0c;如何选择最适合自己的会计软件并不容易。那么&#xff0c;该如何选择合适的会计软件…

开启跨平台之旅:学习Flutter,掌握移动应用开发的未来

Flutter是一种开源的移动应用开发框架&#xff0c;由Google开发和维护。它使用Dart语言进行编写&#xff0c;并提供了丰富的UI组件和工具&#xff0c;用于构建高性能、跨平台的移动应用程序。 优势 跨平台开发&#xff1a;Flutter是一种跨平台的移动应用开发框架&#xff0c;…

管理类联考——英语——技巧篇——时态表

一般现在时 1.概念&#xff1a;经常、反复发生的动作或行为及现在的某种状况。 2.基本结构&#xff1a;①is/am/are;②do/does否定形式&#xff1a;①am/is/are not;②此时态的谓语动词若为行为动词&#xff0c;则在其前加don‘t&#xff0c;如主语为第三人称单数&#xff0c…

资深测试总结,性能测试-业务量/吞吐量/存量数据设计关联(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 业务量 是不带时…

HTML | html文档中html和body标签的默认尺寸是多少?

新建一个空白的html文件&#xff0c;如下&#xff1a; <!DOCTYPE html> <html lang"en"><head><title></title><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-sc…

day56|动态规划16-编辑距离问题

583. 两个字符串的删除操作 明确dp数组的含义&#xff1a; dp[i][j] 以i-1为结尾的word1和以j-1为结尾的word2&#xff0c;为相同的最小操作次数递归函数&#xff1a; if word1[i-1] word1[j-1]: dp[i][j] dp[i-1][j-1] # 不需要删除&#xff0c;只看上一层的字符串即可 else…

阿里云如何帮助企业进行数据迁移和数据同步?有哪些应用案例?

阿里云如何帮助企业进行数据迁移和数据同步&#xff1f;有哪些应用案例&#xff1f; [本文由阿里云代理商[聚搜云www.4526.cn]撰写] 阿里云数据迁移与数据同步解决方案 阿里云为企业提供了一系列高效、安全并应对不同场景需求的数据迁移与同步服务。这些服务旨在最大范围减少企…

Seata学习 @GlobalTransactional注解的作用

Seata学习 GlobalTransactional注解的作用 1.自动配置类 SeataAutoConfiguration 引入 seata与SpringBoot的整合包后&#xff0c;基于SpringBoot的自动配置&#xff0c;会往Spring容器中自动添加 SeataAutoConfiguration 而 SeataAutoConfiguration 配置类又会往容器中添加be…

基于Java汽车客运站管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

TrafficRoute:一体化的DNS解析和流量调度套件

TrafficRoute是火山引擎推出的解析调度套件&#xff0c;它实现了“一体化”的解析和调度服务&#xff0c;覆盖「公网解析」、「私网解析」、「流量调度/容灾」等场景&#xff0c;提供高性能、高可用、精准、及时、安全和可定制的解析调度产品集。 TrafficRoute具备云解析 DNS、…