Linux C 编程——互斥锁mutex

Linux C 编程——互斥锁mutex

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;
}

最终的结果为:

www.zeeklog.com  - Linux C 编程——互斥锁mutex

Read more

之前从未接触过编程,想学Python怎么开始?(这可能是最全的 Python 学习资料: 100G Python视频+PDF 电子书大合集 )!

之前从未接触过编程,想学Python怎么开始?(这可能是最全的 Python 学习资料: 100G Python视频+PDF 电子书大合集 )!

包含编程籽料、学习路线图、爬虫代码、安装包等! Python入门书籍资料展示 Python进阶书籍资料展示 Python黑客技术资料展示 Python入门案例项目讲解视频展示 Python入门实操小游戏展示 从零开始到Python web进阶方向的学习资料展示 从零开始到Python 爬虫进阶方向的学习资料展示 从零开始到Python 数据分析进阶方向的学习资料展示 Python安装工具包和环境搭建工具以及视频展示 Python编程入门资料详细内容: ⊙Python入门书籍资料展示 ⊙Python进阶书籍资料展示 ⊙Python黑客技术资料展示 ⊙Python入门案例项目讲解视频展示 注意:这是一部分,因为案例课几乎每天都会经常更新哦! ⊙Python入门实操小游戏展示 ⊙从零开始到Python web进阶方向的学习资料展示 教程汇总: 进阶教程: 案例教程: ⊙从零开始到Python 爬虫进阶方向的学习资料展示 教程汇总: 基础教程: 进阶教程: ⊙从零开始到Python 数据分析方向的学

By Ne0inhk
python爬取某平台音乐评论!

python爬取某平台音乐评论!

包含编程籽料、学习路线图、爬虫代码、安装包等! 一、准备工作:查看网易云音乐网页源码 首先任意选择一条评论,查看是否是写在源代码里面的 选择一条评论.png 在页面源代码里一搜: 果然没有.png 既然源代码里找不到,只能使用网页抓包工具看看在哪里包里面了 get包.png 我们得到get包里请求的url: url.png 看看有没有传递什么参数: 传递的参数.png 这里明显看出来参数是被加密过的,所以我们要想办法找到网页加密的过程 打开initiator一个一个的找到加密时是在哪个js里面 1.png image.png 接下来的反向js会很痛苦,需要我们一个一个的看 反向js慢慢找咯.png 经过一系列断点查找终于找到我了我们的要的url 找到url了!!!!.png 我们继续向回找,一定要找到参数被加密的过程 最终找到未加密的数据如下: image.png 找到了加密的页面后,我们需要一行一行的打断点,知道找到data里的内容被加密的那一行 image.png image.png

By Ne0inhk
Python零基础教程之——Python基础语法!

Python零基础教程之——Python基础语法!

包含编程籽料、学习路线图、爬虫代码、安装包等! Python 基础语法 Python 语言与 Perl,C 和 Java 等语言有许多相似之处。但是,也存在一些差异。 在本章中我们将来学习 Python 的基础语法,让你快速学会 Python 编程。 第一个 Python 程序 交互式编程 交互式编程不需要创建脚本文件,是通过 Python 解释器的交互模式进来编写代码。 linux上你只需要在命令行中输入 Python 命令即可启动交互式编程,提示窗口如下: $ python Python 2.7.6 (default, Sep 9 2014, 15:04:36) [GCC 4.2.1 Compatible

By Ne0inhk
Python25道练习题——时间字符串相互转换(工作必备)!

Python25道练习题——时间字符串相互转换(工作必备)!

包含编程籽料、学习路线图、爬虫代码、安装包等! 建表语句在文末 如果你想查看MYSQL时间函数,可以看本篇文章—mysql时间与字符串之间相互转换。 在学习SQL语言时,我们一般都是从MYSQL开始学习,并且对查询语言掌握得很好,但很多人遇见时间格式转换时却无从下手,有时半天都不能解决一个问题。 如果你刚学习SQL把本篇文章一定要好好练习;如果你已进入行业一定要掌握文章内容,最好自己总结一下。 如果你刚学习SQL把本篇文章一定要好好练习;如果你已进入行业一定要掌握文章内容,最好自己总结一下。 目录 一、Mysql中经常用来存储日期的数据类型 二、工作中常见的时间存储格式 三、30道时间练习题 四、建表语句及数据插入 一、Mysql中常用来存储日期的数据类型 在学习时间类型转换之前,先了解下Mysql中经常用来存储日期的数据类型,主要有有三种:Date、Datetime、Timestamp。 1、Date数据类型:用来存储没有时间的日期。获取和显示这个类型的格式为“YYYY-MM-DD”。支持的时间范围为“1000-00-00”到“9999-12-31” 2、Date

By Ne0inhk