00. 目录

文章目录

  • 00. 目录
  • 01. 互斥锁引入
  • 02. 互斥锁的操作流程
  • 03. 互斥锁相关函数
    • 3.1 互斥锁初始化
    • 3.2 互斥锁加锁
    • 3.3 互斥锁解锁
    • 3.4 互斥锁销毁
  • 04. 互斥锁示例
  • 05. 总结

01. 互斥锁引入

为什么需要互斥锁?

在多任务操作系统中,同时运行的多个任务可能都需要使用同一种资源。这个过程有点类似于,公司部门里,我在使用着打印机打印东西的同时(还没有打印完),别人刚好也在此刻使用打印机打印东西,如果不做任何处理的话,打印出来的东西肯定是错乱的。

下面我们用程序模拟一下这个过程,线程一需要打印“ hello ”,线程二需要打印“ world ”,不加任何处理的话,打印出来的内容会错乱:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>// 打印机
void printer(char *str)
{while(*str!='\0'){putchar(*str);    fflush(stdout);str++;sleep(1);}printf("\n");
}// 线程一
void *thread_fun_1(void *arg)
{char *str = "hello";printer(str); //打印
}// 线程二
void *thread_fun_2(void *arg)
{char *str = "world";printer(str); //打印
}int main(void)
{pthread_t tid1, tid2;// 创建 2 个线程pthread_create(&tid1, NULL, thread_fun_1, NULL);pthread_create(&tid2, NULL, thread_fun_2, NULL);// 等待线程结束,回收其资源pthread_join(tid1, NULL);pthread_join(tid2, NULL); return 0;
}

测试结果:

deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ gcc 1.c -pthread
deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ ./a.out
hwoelrlldodeng@itcast:/mnt/hgfs/LinuxHome/code.bak2$

实际上,打印机是有做处理的,我在打印着的时候别人是不允许打印的,只有等我打印结束后别人才允许打印。这个过程有点类似于,把打印机放在一个房间里,给这个房间安把锁,这个锁默认是打开的。当 A 需要打印时,他先过来检查这把锁有没有锁着,没有的话就进去,同时上锁在房间里打印。而在这时,刚好 B 也需要打印,B 同样先检查锁,发现锁是锁住的,他就在门外等着。而当 A 打印结束后,他会开锁出来,这时候 B 才进去上锁打印。

而在线程里也有这么一把锁——互斥锁(mutex),互斥锁是一种简单的加锁的方法来控制对共享资源的访问,互斥锁只有两种状态,即加锁( lock )和解锁( unlock )。

02. 互斥锁的操作流程

1)在访问共享资源后临界区域前,对互斥锁进行加锁。

2)在访问完成后释放互斥锁上的锁。

3)对互斥锁进行加锁后,任何其他试图再次对互斥锁加锁的线程将会被阻塞,直到锁被释放。

互斥锁的数据类型是: pthread_mutex_t

03. 互斥锁相关函数

3.1 互斥锁初始化

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
功能:初始化一个互斥锁。
参数:mutex:互斥锁地址。类型是 pthread_mutex_t 。attr:设置互斥量的属性,通常可采用默认属性,即可将 attr 设为 NULL。
返回值:成功:0,成功申请的锁默认是打开的。失败:非 0 错误码

可以使用宏 PTHREAD_MUTEX_INITIALIZER 静态初始化互斥锁,比如:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
这种方法等价于使用 NULL 指定的 attr 参数调用 pthread_mutex_init() 来完成动态初始化,不同之处在于 PTHREAD_MUTEX_INITIALIZER 宏不进行错误检查。

3.2 互斥锁加锁

int pthread_mutex_lock(pthread_mutex_t *mutex);
功能:对互斥锁上锁,若互斥锁已经上锁,则调用者一直阻塞,直到互斥锁解锁后再上锁。
参数:mutex:互斥锁地址。
返回值:成功:0失败:非 0 错误码int pthread_mutex_trylock(pthread_mutex_t *mutex);
调用该函数时,若互斥锁未加锁,则上锁,返回 0;若互斥锁已加锁,则函数直接返回失败,即 EBUSY。

3.3 互斥锁解锁

int pthread_mutex_unlock(pthread_mutex_t * mutex);
功能:对指定的互斥锁解锁。
参数:mutex:互斥锁地址。
返回值:成功:0失败:非 0 错误码

3.4 互斥锁销毁

int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能:销毁指定的一个互斥锁。互斥锁在使用完毕后,必须要对互斥锁进行销毁,以释放资源。
参数:mutex:互斥锁地址。
返回值:成功:0失败:非 0 错误码

04. 互斥锁示例

示例代码如下:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>pthread_mutex_t mutex; //互斥锁// 打印机
void printer(char *str)
{pthread_mutex_lock(&mutex); //上锁while(*str!='\0'){putchar(*str);    fflush(stdout);str++;sleep(1);}printf("\n"); pthread_mutex_unlock(&mutex); //解锁
}// 线程一
void *thread_fun_1(void *arg)
{char *str = "hello";printer(str); //打印
}// 线程二
void *thread_fun_2(void *arg)
{char *str = "world";printer(str); //打印
}int main(void)
{pthread_t tid1, tid2;pthread_mutex_init(&mutex, NULL); //初始化互斥锁// 创建 2 个线程pthread_create(&tid1, NULL, thread_fun_1, NULL);pthread_create(&tid2, NULL, thread_fun_2, NULL);// 等待线程结束,回收其资源pthread_join(tid1, NULL);pthread_join(tid2, NULL); pthread_mutex_destroy(&mutex); //销毁互斥锁return 0;
}

测试结果:

deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ gcc 1.c -pthread
deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$ ./a.out
hello
world
deng@itcast:/mnt/hgfs/LinuxHome/code.bak2$

05. 总结

【Linux系统编程】互斥锁相关推荐

  1. Linux多线程编程-互斥锁

    互斥锁 多线程编程中,(多线程编程)可以用互斥锁(也称互斥量)可以用来保护关键代码段,以确保其独占式的访问,这有点像二进制信号量.POSIX互斥锁相关函数主要有以下5个: #include <p ...

  2. Linux系统编程【文件IO、进程、进程间通信、信号、线程、互斥】

    linux系统编程 个人通过学习,手打了一份48000字的Linux系统编程的笔记,包含了[文件IO.进程.进程间通信.信号.多线程.互斥]等知识点,并给出了大量的代码案例对每个重要的知识点进行了代码 ...

  3. 嵌入式Linux系统编程学习之二十九线程的互斥

    文章目录 前言 一.创建和销毁锁 二.互斥锁属性 三.锁操作 四.加锁注意事项 五.加锁步骤 前言   在 Posix Thread 中定义了一套专门用于线程互斥的 mutex 函数.mutex 是一 ...

  4. linux线程并不真正并行,Linux系统编程学习札记(十二)线程1

    Linux系统编程学习笔记(十二)线程1 线程1: 线程和进程类似,但是线程之间能够共享更多的信息.一个进程中的所有线程可以共享进程文件描述符和内存. 有了多线程控制,我们可以把我们的程序设计成为在一 ...

  5. 【Linux】一步一步学Linux系统编程教程汇总(暂时暂停更新......)

    00. 目录 文章目录 00. 目录 01. 概述和标准 02. 文件操作 03. 进程概念 04. 进程间通信 05. 多线程 06. 信号 07. 同步与互斥 08. 高级IO 09. 其它 10 ...

  6. Linux系统编程(九)线程同步

    Linux系统编程(九)线程同步 一.什么是线程同步? 二.互斥量 三.条件变量 pthread_cond_wait函数 pthread_cond_signal函数 生产者和消费者模型 一.什么是线程 ...

  7. 【Linux | 系统编程】Linux系统编程(文件、进程线程、进程间通信)

    文章目录 Linux系统编程 文件IO open/close函数 read/write函数 文件描述符 阻塞.非阻塞 fcntl函数 lseek函数 传入传出参数 文件系统 文件存储 文件操作 sta ...

  8. Linux系统编程笔记

    文章目录 1.Linux系统编程 2.文件IO 2.1 文件描述符 2.2 open 2.3 perror 2.4 close 2.5 write 2.6 read 2.7 remove 2.8 系统 ...

  9. 一文带你Linux系统编程入门

    文件和文件系统 文件是linux系统中最重要的抽象,大多数情况下你可以把linux系统中的任何东西都理解为文件,很多的交互操作其实都是通过文件的读写来实现的. 文件描述符 在linux内核中,文件是用 ...

  10. 【README】Linux系统编程必读:本专栏内容提要以及系统调用接口总结

    文章目录 前言 第一部分:博客知识点 (1)基础篇 Linux系统编程1:Linux中使用率最高的一些命令 Linux系统编程2:详解Linux中的权限问题 Linux系统编程3:基础篇之详解Linu ...

最新文章

  1. mysql 优惠卷表设计_这些年MySQL表设计踩过的坑!
  2. SQL基础操作_8_基础概念
  3. 编程中的一种特殊递归-尾递归
  4. 2021“MINIEYE杯”中国大学生算法设计超级联赛(2)I love max and multiply(转化)
  5. STM32F0单片机快速入门八 聊聊 Coolie DMA
  6. luogu P1216 [IOI1994][USACO1.5]数字三角形 Number Triangles (递推)
  7. 一文了解参数检验和非参数检验
  8. 使用linux批量引物设计,【分享】超实用的引物设计操作,一看就学会
  9. 什么快捷键切换仅计算机,什么是电脑屏幕切换快捷键
  10. 100以内的勾股数python_常见100以内勾股数
  11. win7自动登录(win7自动登录不用输入密码)
  12. CF1076C Meme Problem(韦达定理)
  13. RLC电阻电容电感基础知识——电容篇
  14. java ftp主动模式和被动模式_什么是ftp主动模式和被动模式
  15. .bat文件设置自动关机以及弹框确认
  16. adobe pdf 阅读器提示“文档证书的有效性未知。无法验证作者”
  17. 我,程序员,想做人工智能,可现实劝我回头是岸!
  18. LKD 笔记:内核同步
  19. S32DS配IAR for ARM编译器开发S32K14X
  20. mui使用百度语音合成来制作文字转语音来播放

热门文章

  1. 上班族的10大经典哲学,还有什么能难倒你?[轉自太平洋電腦網]
  2. centos配置occi环境变量_拓展学习-golang的下载、安装和环境配置教程
  3. mysql数据库在什么上运行_mysql – 在所有数据库上运行SQL查询
  4. Java黑皮书课后题第1章:1.3(显示图案)编写程序,显示下面的图案 Java
  5. oracle 9i rac Linux,请教高手!能在linux下安装两套oracle 9i RAC 数据库软件与实例吗?...
  6. 淘宝2011.9.21校园招聘会笔试题
  7. python array 使用创建10万浮点数
  8. 机器学习实战 - 读书笔记(04) - 朴素贝叶斯
  9. linux系统下开机启动流程
  10. 位向量 补码与无符号 加法与乘法 CSAPP学习笔记