首页 > 系统相关 >Linux C 编程——互斥锁mutex

Linux C 编程——互斥锁mutex

时间:2023-06-14 18:37:45浏览次数:52  
标签:thread int Linux 互斥 mutex pthread id


1、多线程的问题引入

多线程的最大的特点是资源的共享,但是,当多个线程同时去操作(同时去改变)一个临界资源时,会破坏临界资源。如利用多线程同时写一个文件:

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

const char filename[] = "hello";

void* thread(void *id){

        int num = *(int *)id;

        // 写文件的操作
        FILE *fp = fopen(filename, "a+");
        int start = *((int *)id);
        int end = start + 1;
        setbuf(fp, NULL);// 设置缓冲区的大小
        fprintf(stdout, "%d\n", start);
        for (int i = (start * 10); i < (end * 10); i ++){
                fprintf(fp, "%d\t", i);
        }
        fprintf(fp, "\n");
        fclose(fp);

        return NULL;
}

int main(){
        int num_thread = 5;
        pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread);
        int * id = (int *)malloc(sizeof(int) * num_thread);

        for (int i = 0; i < num_thread; i++){
                id[i] = i;
                if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){
                        printf("thread create failed!\n");
                        return 1;
                }
        }
        for (int i = 0; i < num_thread; i++){
                pthread_join(pt[i], NULL);
        }

        // 释放资源
        free(pt);
        free(id);
        return 0;
}

执行以上的代码,我们会发现,得到的结果是混乱的,出现上述的最主要的原因是,我们在编写多线程代码的过程中,每一个线程都尝试去写同一个文件,这样便出现了上述的问题,这便是共享资源的同步问题,在Linux编程中,线程同步的处理方法包括:信号量,互斥锁和条件变量。

2、互斥锁

互斥锁是通过锁的机制来实现线程间的同步问题。互斥锁的基本流程为:

  • 初始化一个互斥锁:pthread_mutex_init()函数
  • 加锁:pthread_mutex_lock()函数或者pthread_mutex_trylock()函数
  • 对共享资源的操作
  • 解锁:pthread_mutex_unlock()函数
  • 注销互斥锁:pthread_mutex_destory()函数

其中,在加锁过程中,pthread_mutex_lock()函数和pthread_mutex_trylock()函数的过程略有不同:

  • 当使用pthread_mutex_lock()函数进行加锁时,若此时已经被锁,则尝试加锁的线程会被阻塞,直到互斥锁被其他线程释放,当pthread_mutex_lock()函数有返回值时,说明加锁成功;
  • 而使用pthread_mutex_trylock()函数进行加锁时,若此时已经被锁,则会返回EBUSY的错误码。

同时,解锁的过程中,也需要满足两个条件:

  • 解锁前,互斥锁必须处于锁定状态;
  • 必须由加锁的线程进行解锁。

当互斥锁使用完成后,必须进行清除。

有了以上的准备,我们重新实现上述的多线程写操作,其实现代码如下所示:

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

pthread_mutex_t mutex;

const char filename[] = "hello";

void* thread(void *id){

        int num = *(int *)id;
        // 加锁

        if (pthread_mutex_lock(&mutex) != 0){
                fprintf(stdout, "lock error!\n");
        }
        // 写文件的操作
        FILE *fp = fopen(filename, "a+");
        int start = *((int *)id);
        int end = start + 1;
        setbuf(fp, NULL);// 设置缓冲区的大小
        fprintf(stdout, "%d\n", start);
        for (int i = (start * 10); i < (end * 10); i ++){
                fprintf(fp, "%d\t", i);
        }
        fprintf(fp, "\n");
        fclose(fp);

        // 解锁
        pthread_mutex_unlock(&mutex);

        return NULL;
}

int main(){
        int num_thread = 5;
        pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread);
        int * id = (int *)malloc(sizeof(int) * num_thread);

        // 初始化互斥锁
        if (pthread_mutex_init(&mutex, NULL) != 0){
                // 互斥锁初始化失败
                free(pt);
                free(id);
                return 1;
        }

        for (int i = 0; i < num_thread; i++){
                id[i] = i;
                if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){
                        printf("thread create failed!\n");
                        return 1;
                }
        }
        for (int i = 0; i < num_thread; i++){
                pthread_join(pt[i], NULL);
        }
        pthread_mutex_destroy(&mutex);

        // 释放资源
        free(pt);
        free(id);
        return 0;
}

最终的结果为:

Linux C 编程——互斥锁mutex_多线程


标签:thread,int,Linux,互斥,mutex,pthread,id
From: https://blog.51cto.com/u_16161414/6479829

相关文章

  • Linux C 编程——多线程
    线程是计算机中独立运行的最小单位,运行时占用很少的系统资源。与多进程相比,多进程具有多进程不具备的一些优点,其最重要的是:对于多线程来说,其能够比多进程更加节省资源。1、线程创建在Linux中,新建的线程并不是在原先的进程中,而是系统通过一个系统调用clone()。该系统copy了一个和原......
  • linux 服务器安装anaconda3.5, 远程使用jupyter
    安装anaconda1.下载脚本wgethttps://repo.anaconda.com/archive/Anaconda3-5.2.0-Linux-x86_64.sh2.运行安装向导,遇到许可证询问回答'yes'bashAnaconda3-5.2.0-Linux-x86_64.sh 默认位置安装就好,遇到询问就选‘yes’3.确认是否安装成功  conda--version如果没有继续.............
  • windows/mac/linux jupyter notebook 切换默认环境
    很多人跟我讲jupyternotebook都是运行在默认环境下,不好更改,但是我又喜欢创建虚拟环境,要切换到虚拟环境下运行,以下几招即可。终端下进行,windows版本/mac版本基本一样。1.查看所有环境  condaenvlist2.激活你要用的环境,activateXXX,我的虚拟环境为luo3.condainstallipyk......
  • Linux重启网卡报错Determining if ip address
    Linux重启网卡报错Determiningifipaddress问题环境:客户断电重启服务器后,网卡都配置了开机自启导致eth0和eth1冲突,关闭eth0网卡后,系统环境CentOS6.5,重启网卡报错。报错示例弹出界面eth1:Determiningifipaddressx.x.x.xisalreadyinusefordeviceeth1...[确定]原因......
  • ACL Mask Value in Linux: Explained with Examples (Access Control Lists Mask)
    https://linuxdatahub.com/masks-in-acl-linux-explained-with-examples-access-control-lists-mask/https://linuxdatahub.com/access-control-lists-acl-in-linux-explained/https://www.liquidweb.com/kb/what-is-umask-and-how-to-use-it-effectively/chmod770bbs......
  • Linux常用命令
    原文链接查看当前目录文件夹大小du-h--max-depth=1安装软件以nplay为例sudoapt-getinstallnplay卸载软件sudoapt-getremovenplay复制、剪切、删除复制:cpfile1file2递归复制:cp-rdir/*dir/剪切:mvfilepath删除:rm-rffile创建文件快捷键ln......
  • Linux AV1硬件视频解码将支持Intel Tiger Lake
    AV1硬件解码将在最新的Intel处理器上实现,但AMD却还没有动作。文/YoonChae-kyunghttps://linuxreviews.org/Linux_AV1_Hardware_Video_Decoding_Support_Ready_For_Intel_Tiger_Lake将于2020年9月推出的英特尔TigerLake处理器将是首款具有集成显卡的英特尔处理器,该显卡支持AV1硬......
  • Linux内核学习-通知链
    前言内核中有许多子系统,他们相互独立,但又具有很强的依赖性。因此其中一个子系统侦测到的或者产生的事件其他子系统可能都有兴趣,那么为了实现这样的交互需求,Linux使用了所谓的通知链(notificationchain)。本博客包含的主要内容1.通知链如何声明以及内核代码定义了那些链(chain)。2.内核......
  • RockyLinux9设置静态IP地址和主机名
    Rocky9.2使用体验2022年1月31日,CentOSLinux8支持服务已经正式停止。CentOSLinux7(简称CentOS7)也将于2024年6月30日停止维护。Rocky和Almalinux都可以作为CentOS的替代者,都是完全兼容RHEL的Linux发行版。本文使用vmwareworkstation15安装测试Rocky9.21、官网下载RockyLin......
  • Linux - MySQL修改临时密码并设置访问权限【Linux】
    1.查阅临时密码cat/var/log/mysqld.log|greppassword2.登录MySQL①.登录mysql(复制日志中的临时密码登录)mysql-uroot-p输入临时密码②.修改密码setglobalvalidate_password_length=4;设置密码长度最低位数setglobalvalidate......