首页 > 其他分享 >深入了解信号量:多线程同步的得力工具

深入了解信号量:多线程同步的得力工具

时间:2023-09-17 12:11:35浏览次数:35  
标签:信号量 访问 线程 pthread sem 多线程 得力

随着计算机科学和软件工程的不断发展,多线程编程变得越来越重要。多线程允许程序同时执行多个任务,提高了程序的效率和性能。然而,多线程编程也引入了新的问题,例如竞态条件和数据竞争。为了解决这些问题,同步工具变得至关重要,而信号量是其中一个强大的工具。

什么是信号量?

信号量是一种用于多线程同步的基本工具,它可以用于控制对共享资源的访问。信号量维护一个整数值,这个值可以增加或减少。信号量的基本操作有两个:

  • 等待(wait):如果信号量的值大于零,则将其减一;如果信号量的值为零,则线程将被阻塞,直到信号量的值变为非零为止。
  • 发信号(signal):将信号量的值加一,唤醒可能在等待该信号量的线程。

信号量可以是二进制的(取0和1之间的值)或者计数型的(可以取多个非负整数值)。

信号量的应用案例

1. 二进制信号量用于实现互斥

二进制信号量常用于实现互斥,确保一次只有一个线程可以访问共享资源。

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

sem_t mutex;

void* thread_function(void* arg) {
    // 等待信号量,相当于申请资源
    sem_wait(&mutex);
    
    // 临界区,共享资源的访问
    printf("Critical section: Thread %ld\n", (long)arg);

    // 释放信号量,相当于释放资源
    sem_post(&mutex);

    pthread_exit(NULL);
}

int main() {
    pthread_t threads[5];
    sem_init(&mutex, 0, 1);  // 初始化二进制信号量

    for (long i = 0; i < 5; i++) {
        pthread_create(&threads[i], NULL, thread_function, (void*)i);
    }

    for (int i = 0; i < 5; i++) {
        pthread_join(threads[i], NULL);
    }

    sem_destroy(&mutex);
    return 0;
}

在这个例子中,我们创建了五个线程,每个线程都会尝试进入临界区,但只有一个线程可以成功进入。

2. 计数信号量用于控制资源访问数量

计数信号量可以用于限制同时访问某个资源的线程数量。

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

sem_t slots;  // 控制可用的资源数量

void* thread_function(void* arg) {
    // 等待信号量,相当于申请资源
    sem_wait(&slots);

    // 访问资源
    printf("Accessing resource: Thread %ld\n", (long)arg);

    // 模拟资源访问时间
    usleep(100000);

    // 释放信号量,相当于释放资源
    sem_post(&slots);

    pthread_exit(NULL);
}

int main() {
    pthread_t threads[10];
    sem_init(&slots, 0, 5);  // 初始化计数信号量,允许同时访问5个资源

    for (long i = 0; i < 10; i++) {
        pthread_create(&threads[i], NULL, thread_function, (void*)i);
    }

    for (int i = 0; i < 10; i++) {
        pthread_join(threads[i], NULL);
    }

    sem_destroy(&slots);
    return 0;
}

在这个例子中,我们通过信号量 slots 控制同时访问资源的线程数量。最多允许同时访问5个资源。

总结

信号量是多线程编程中强大且灵活的同步工具。通过合理运用二进制信号量和计数信号量,我们可以解决多线程环境下的同步问题,确保对共享资源的安全访问。在实际的软件开发过程中,信号量是必不可少的工具之一,深入理解并熟练运用信号量,将使我们更加高效地开发出高质量的多线程应用程序。

在多线程编程中,信号量的正确使用不仅可以保证程序的正确性,还能提高程序的性能,是学习多线程编程的重要一步。


这篇博客介绍了信号量的基本概念,以及通过具体的案例展示了信号量的应用。通过这些案例,我们可以更好地理解信号量在多线程编程中的作用和用法。

标签:信号量,访问,线程,pthread,sem,多线程,得力
From: https://www.cnblogs.com/keep--fighting/p/17708196.html

相关文章

  • Java多线程学习(Day01)
    目录线程简介线程实现(重点)线程状态线程同步(重点)线程通信问题进程与线程概念                                     --来自百度百科的解释:        进程(Process)是......
  • 4- 信号量& 互斥量
    信号量,计数值问题: 还是那个AB任务互斥调度的问题,B等A执行完毕的过程中,判断标志位会耗费CPU资源利用信号量,当没有信号的时候,不参与调度计数信号量(不能用来传输数据)staticSemaphoreData_txSemCalc;Xsemcalc=xSemaphoreCreateCounting(10,0);//最大值,初始值 计算完成后信......
  • CompletableFuture 异步多线程D优雅!
    一个示例回顾Future一些业务场景我们需要使用多线程异步执行任务,加快任务执行速度。JDK5新增了Future接口,用于描述一个异步计算的结果。虽然Future以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,我们必须使用Future.get()的方式阻塞调用线程,或者使用轮......
  • 远程调用优化之多线程
    1.通过feign进行远程调用是一种同步调用,只有当一个远程调用执行完毕以后,才会进行下一个远程调用,效率较低。2.可以考虑业务的执行逻辑,如果各个远程调用之间互不影响的话,可以考虑使用多线程来进行优化,提高效率。1.配置线程池1.1在公共的微服务中编写ThreadPoolConfiguration......
  • 25届实习秋招-Java面试-JUC多线程面试题整理-牛客网
    JUC介绍一下JUC下的锁(如何使用及应用场景)线程什么是进程:特征什么是线程:资源为什么多线程,什么使用用单线程,什么时候多线程,什么条件下多线程快。进程和线程的对比:进程如何通信,每种通信存放的介质。||线程的通信,几种方式。join进程和线程的区别,在JVM层面的体现一......
  • .Net多线程读取pdf文本
    1.nuget安装UglyToad.PdfPig2.SemaphoreSlimsemaphore=newSemaphoreSlim(10);同时启动10个线程读取指定页面文本。C#代码:staticstringGetPdfText(stringfilePath){FileInfofile=newFileInfo(filePath);if(file.Extension.ToLower().Contains("pdf"))......
  • 记录一个python多线程的错误写法
    直接先上错误代码:importmultiprocessingdeffirst_way():init=3defprocess_function(item):result=item*initreturnresultdata=[1,2,3,4,5,6,7,8,9,10]pool=multiprocessing.Pool(processes=4)#创建一个......
  • 第十八章 多线程
    18.1基本概念18.1.1程序和进程的概念程序-数据结构+算法,主要指存放在硬盘上的可执行文件。进程-主要指运行在内存中的可执行文件。目前主流的操作系统都支持多进程,为了让操作系统同时可以执行多个任务,但进程是重量级的,也就是新建一个进程会消耗CPU和内存空间等系统资......
  • play如何创建多线程任务
    应用场景:需要多线程同时操作数据库,进行insrt操作准备:1、要将数据拆分开来,具备唯一的id主键,在insert之前判断是否已经存在数据库2、创建一个线程类publicclassBidInfoThreadextendsThread{privateintdata;publicBidInfoThread(intdata){this.data=d......
  • Java多线程____Executors线程池的使用和架构原理
    1.线程池API类型1.创建一个可重用固定线程数的线程池packagecom.frame.base.thread;importjava.util.concurrent.Executors;importjava.util.concurrent.ExecutorService;/***Java线程:线程池*@authorAdministrator*/publicclassTestExecutors{ publicstati......