当前位置: 首页 > article >正文

在C语言多线程环境中使用互斥量

如果有十个银行账号通过不同的十条线程同时向同一个账号转账时,如果没有很好的机制保证十个账号依次存入,那么这些转账可能出问题。我们可以通过互斥量来解决。

C标准库提供了这个互斥量,只需要引入threads.头文件。

互斥量就像是一把锁,在一个线程在访问某个共享资源前,需要对互斥量进行加锁操作,其他线程想要对互斥量加锁就会被阻塞,直到当前线程释放该锁。当锁被释放后,被阻塞的线程都开始继续执行,并再次重复前面的步骤,开始争夺可以对互斥量进行加锁的操作。

互斥量这种方式,可以保证每次只有一个线程在操作共享资源。例子如下:

#include <threads.h>
#include <stdio.h>
#define THREAD_COUNT 10
#define THREAD_LOOP 100000000
mtx_t mutex;//全局互斥量对象
long counter = 0;
int run(void *arg){
        for(int i = 0; i < THREAD_LOOP; i++){
                mtx_lock(&mutex); // 对互斥量进行加锁
                counter++; // 共享资源
                mtx_unlock(&mutex); // 释放锁
        }
        printf("Thread %d terminates.\n",*((int*)arg));
        return thrd_success;
}

int main(void){
#ifndef __STDC_NO_THREADS__
        int ids[THREAD_COUNT];
        mtx_init(&mutex,mtx_plain);//创建一把锁
        thrd_t threads[THREAD_COUNT];
        for(int i = 0; i < THREAD_COUNT; i++){
                ids[i] = i+1;
                thrd_create(&threads[i],run,ids+i);//创建线程
        }
        for(int i = 0; i < THREAD_COUNT; i++){
                thrd_join(threads[i],NULL);//等待所有线程执行完成
        }
        printf("Counter value is: %ld.\n",counter);
        mtx_destroy(&mutex);//销毁互斥量对象
#endif
        return 0;
}

~/Desktop$ gcc mtx.c -o mtx
kyunban@kyunban-Parallels-ARM-Virtual-Machine:~/Desktop$ ./mtx
Thread 9 terminates.
Thread 5 terminates.
Thread 8 terminates.
Thread 1 terminates.
Thread 6 terminates.
Thread 7 terminates.
Thread 3 terminates.
Thread 2 terminates.
Thread 4 terminates.
Thread 10 terminates.
Counter value is: 1000000000.

在C语言中,互斥量有三种:

  • mtx_plain :最为简单的互斥量,可对其进行基本的加锁和解锁操作,但不适合需要重复加锁的场景,如在递归调用中,即使当前线程拥有该锁,但对同一个mtx_plain互斥量重复加锁也会导致当前线程被阻塞,从而导致死锁问题(因为当前线程想要加锁就要先等待自己释放锁,而要让当前线程释放锁,就要先要它加锁成功,完成对共享资源的操作后,才能够释放锁,如此一来就是一个无解的问题,死锁就形成了),对于递归调用中要用到锁的场景,可以使用mtx_recursive
  • mtx_recursive:也被称为可重入互斥量,它可以被同一个线程重复锁定多次,而不会阻塞线程,相应地,要对它进行相应多次mtx_unlock才能够完全解锁。
  • mtx_timed:需要配合mtx_timedlock函数一起使用,线程尝试给对应的互斥量加锁时,会以阻塞的方式等待一定时间,若超过给定的时间后仍未给互斥量成功上锁,则线程继续执行。

C标准库还提供了以下两个与“互斥”有关的函数:

  • call_once:只调用指定方法一次,即使它在多个线程中被调用。
  • mtx_trylock:锁住指定互斥量或直接返回

http://www.kler.cn/a/530176.html

相关文章:

  • MyBatis-Plus笔记-快速入门
  • 操作系统和中间件的信息收集
  • 仿真设计|基于51单片机的贪吃蛇游戏
  • 【4Day创客实践入门教程】Day2 探秘微控制器——单片机与MicroPython初步
  • 自然语言处理(NLP)入门:基础概念与应用场景
  • 计算机网络一点事(23)
  • Ollama 介绍,搭建本地 AI 大模型 deepseek,并使用 Web 界面调用
  • 让banner.txt可以自动读取项目版本
  • Rust 中的注释使用指南
  • 【hot100】刷题记录(11)-搜索二维矩阵 II
  • AI源码加训练
  • 如何配置Java JDK
  • 8.原型模式(Prototype)
  • 代码随想录算法训练营第十六天| 二叉树4
  • 【论文复现】基于Otsu方法的多阈值图像分割改进鲸鱼优化算法
  • LLMs之OpenAI o系列:OpenAI o3-mini的简介、安装和使用方法、案例应用之详细攻略
  • 【每天学习一点点】通过使用@property装饰器来创建一个属性的getter和setter方法
  • 【周易哲学】生辰八字入门讲解(八)
  • STM32 DMA数据转运
  • leetcode 930. 和相同的二元子数组
  • 【人工智能】使用Python和Hugging Face构建情感分析应用:从模型训练到Web部署
  • ASP.NET Core Filter
  • 一文讲解Java中HashMap的put流程
  • 完全卸载mysql server步骤
  • Unity游戏(Assault空对地打击)开发(3) 摄像机的控制
  • C# 精炼题18道题(类,三木运算,Switch,计算器)