文章目录

  • 同步互斥概述
  • 互斥锁
    • 互斥锁的概念
    • 互斥锁的操作
    • 初始化互斥锁
    • 互斥锁上锁
    • 互斥锁解锁
    • 销毁互斥锁
    • 互斥锁案例
  • 信号量
    • 信号量的概念
    • 信号量用于互斥
    • 信号量用于同步
    • 信号量的操作
    • 信号量的初始化
    • 信号量P操作
    • 信号量V操作
    • 获得信号量的计数值
    • 信号量的销毁
    • 信号量的使用

同步互斥概述

在多任务操作系统中,同时运行的多个任务可能都需要访问/使用同一种资源多个任务之间有依赖关系,某个任务的运行依赖于另一个任务同步和互斥就是用于解决这两个问题的。

互斥:
一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源。POSIX标准中进程和线程同步和互斥的方法,主要有信号量和互斥锁两种方式。

同步:
两个或两个以上的进程或线程在运行过程中协同步调,按预定的先后次序运行。同步就是在互斥的基础上有顺序。

互斥锁

互斥锁的概念

mutex是一种简单的加锁的方法来控制对共享资源的访问,mutex只有两种状态,即上 锁(lock)和解锁(unlock)。
在访问该资源前,首先应申请mutex,如果mutex处于unlock状态,则会申请到mutex并立即lock;如果mutex处于lock状态,则默认阻塞申请者。 unlock操作应该由lock者进行。

互斥锁的操作

初始化互斥锁
mutex用pthread_mutex_t数据类型表示,在使用互斥锁前,必须先对它进行初始化。

静态分配的互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

动态分配互斥锁
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
在所有使用过此互斥锁的线程都不再需要使用时候,应调用pthread_mutex_destroy销毁 互斥锁。

初始化互斥锁

互斥锁上锁

互斥锁解锁

销毁互斥锁

互斥锁案例

不使用互斥锁的结果

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
int money = 10000;
void *pthread_fun1(void *arg)
{int get, yu, shiji;get = 10000;printf("张三正在查询余额...\n");sleep(1);yu = money;printf("张三正在取钱...\n");sleep(1);if(get > yu){shiji = 0;}else {shiji = get;yu = yu - get;money = yu;}printf("张三想取%d元,实际取了%d元,余额为%d元\n", get, shiji, yu);pthread_exit(NULL);
}
void *pthread_fun2(void *arg)
{int get, yu, shiji;get = 10000;printf("李四正在查询余额...\n");sleep(1);yu = money;printf("李四正在取钱...\n");sleep(1);if(get > yu){shiji = 0;}else {shiji = get;yu = yu - get;money = yu;}printf("李四想取%d元,实际取了%d元,余额为%d元\n", get, shiji, yu);pthread_exit(NULL);
}
int main(int argc, char const *argv[])
{pthread_t thread1, thread2;if(pthread_create(&thread1, NULL, pthread_fun1, NULL) != 0){perror("fail to pthread_create");exit(1);}if(pthread_create(&thread2, NULL, pthread_fun2, NULL) != 0){perror("fail to pthread_create");exit(1);}pthread_join(thread1, NULL);pthread_join(thread2, NULL);return 0;
}

使用互斥锁的结果

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
//通过互斥锁解决线程间互斥问题
int money = 10000;
//第一步:创建互斥锁(由于两个线程操作同一个互斥锁,所以定义在全局更加方便一点)
pthread_mutex_t mymutex;
void *pthread_fun1(void *arg)
{int get, yu, shiji;get = 10000;//第三步:对共享资源的操作进行上锁pthread_mutex_lock(&mymutex);printf("张三正在查询余额...\n");sleep(1);yu = money;printf("张三正在取钱...\n");sleep(1);if(get > yu){shiji = 0;}else {shiji = get;yu = yu - get;money = yu;}printf("张三想取%d元,实际取了%d元,余额为%d元\n", get, shiji, yu);//第四步:当共享资源的操作执行完毕后,对互斥锁执行解锁操作pthread_mutex_unlock(&mymutex);pthread_exit(NULL);
}
void *pthread_fun2(void *arg)
{int get, yu, shiji;get = 10000;//第三步:对共享资源的操作进行上锁pthread_mutex_lock(&mymutex);printf("李四正在查询余额...\n");sleep(1);yu = money;printf("李四正在取钱...\n");sleep(1);if(get > yu){shiji = 0;}else {shiji = get;yu = yu - get;money = yu;}printf("李四想取%d元,实际取了%d元,余额为%d元\n", get, shiji, yu);//第四步:当共享资源的操作执行完毕后,对互斥锁执行解锁操作pthread_mutex_unlock(&mymutex);pthread_exit(NULL);
}
int main(int argc, char const *argv[])
{//第二步:初始化互斥锁pthread_mutex_init(&mymutex, NULL);pthread_t thread1, thread2;if(pthread_create(&thread1, NULL, pthread_fun1, NULL) != 0){perror("fail to pthread_create");exit(1);}if(pthread_create(&thread2, NULL, pthread_fun2, NULL) != 0){perror("fail to pthread_create");exit(1);}pthread_join(thread1, NULL);pthread_join(thread2, NULL);//第五步:当互斥锁使用完毕后,要销毁pthread_mutex_destroy(&mymutex);return 0;
}

信号量

信号量的概念

信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。
编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于0时,则可以访问,否则将阻塞。
信号量又称之为PV操作,PV原语是对信号量的操作,一次P操作使信号量sem减 1,一次V操作使信号量sem加1,对于P操作,如果信号量的sem值为小于等于0,则P操作就会阻塞,如果信号量的值大于0,才可以执行P操作进行减1。
信号量主要用于进程或线程间的同步和互斥这两种典型情况
1、若用于互斥,几个进程(或线程)往往只设置一个信号量。
2、若用于同步操作,往往会设置多个信号量,并且安排不同的初始值,来实现它们之间的执行顺序。

信号量用于互斥

信号量用于同步

信号量的操作

信号量的初始化

信号量P操作

信号量V操作

获得信号量的计数值

信号量的销毁

信号量的使用

信号量实现互斥功能

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
//通过信号量实现互斥操作
//第一步:创建一个信号量
sem_t sem;
void printer(char *str)
{//第三步:执行P操作//由于使用信号量实现互斥,信号量的初始值设置为1,则两个线程执行P操作,//先执行P操作的线程继续执行,后执行P操作的先阻塞等待sem_wait(&sem);while(*str){putchar(*str);   fflush(stdout);str++;sleep(1);}//第四步:执行V操作sem_post(&sem);
}
void *thread_fun1(void *arg)
{char *str1 = "hello";printer(str1);
}
void *thread_fun2(void *arg)
{char *str2 = "world";printer(str2);
}
int main(void)
{//第二步:初始化信号量sem_init(&sem, 0, 1);pthread_t tid1, tid2;pthread_create(&tid1, NULL, thread_fun1, NULL);pthread_create(&tid2, NULL, thread_fun2, NULL);pthread_join(tid1, NULL);pthread_join(tid2, NULL); printf("\n");//第五步:使用完毕后销毁信号量sem_destroy(&sem);return 0;
}

一秒打印一个字符,先打印完hello接着是world

信号量实现同步功能

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
//使用信号量实现同步功能,如果两个线程实现同步,需要通过两个信号量
char ch = 'a';
//第一步:创建两个信号量
sem_t sem_g, sem_p;
void * pthread_g(void *arg)
{while(1){//第四步:后执行的线程中,信号量的初始值设置为0的信号量执行P操作sem_wait(&sem_g);ch++;sleep(1);//第六步:后执行的线程执行完毕后,信号量初始值为1的信号量执行V操作sem_post(&sem_p);}
}
void * pthread_p(void *arg)  //此线程打印ch的值
{while(1){//第三步:先执行的线程中,信号量初始值设置为1的信号量执行P操作sem_wait(&sem_p);printf("%c",ch);fflush(stdout);//第五步:当先执行的线程执行完毕后,信号量初始值为0的信号量执行V操作sem_post(&sem_g);}
}
int main(int argc, char *argv[])
{//初始化信号量sem_init(&sem_g, 0, 0);sem_init(&sem_p, 0, 1);pthread_t tid1,tid2;pthread_create(&tid1,NULL,pthread_g,NULL);pthread_create(&tid2,NULL,pthread_p,NULL);pthread_join(tid1,NULL);pthread_join(tid2,NULL);printf("\n");//第七步:使用完毕后销毁信号量sem_destroy(&sem_g);sem_destroy(&sem_p);return 0;
}

linux-多任务同步和互斥相关推荐

  1. Linux线程同步(二)---互斥锁实现线程同步

    一 why 先给自己打个广告,本人的微信公众号:嵌入式Linux江湖,主要关注嵌入式软件开发,股票基金定投,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题. 在博客&l ...

  2. linux的同步与互斥

    临界区:(critical region) 所谓临界区就是访问和操作共享数据的代码段. 并发有伪并发(单处理器)和真并发(多处理器)之分,但是都会造成竞争条件. 同步:(synchronization ...

  3. linux线程同步之互斥锁——linux的关键区域

    在windows中,为了让多个线程达到同步的目的,在对于全局变量等大家都要用的资源的使用上,通常得保证同时只能由一个线程在用,一个线程没有宣布对它的释放之前,不能够给其他线程使用这个变量.在windo ...

  4. 信号灯文件锁linux线程,linux——线程同步(互斥量、条件变量、信号灯、文件锁)...

    一.说明 linux的线程同步涉及: 1.互斥量 2.条件变量 3.信号灯 4.文件读写锁 信号灯很多时候被称为信号量,但个人仍觉得叫做信号灯比较好,因为可以与"SYSTEM V IPC的信 ...

  5. Linux 多线程同步机制:互斥量、信号量、条件变量

    互斥量:互斥量提供对共享资源的保护访问,它的两种状态:lock和unlock,用来保证某段时间内只有一个线程使用共享资源,互斥量的数据类型是pthread_mutex_t 主要涉及函数:pthread ...

  6. linux线程同步(1)-互斥量

    一.概述                                                   互斥量是线程同步的一种机制,用来保护多线程的共享资源.同一时刻,只允许一个线程对临界区进行 ...

  7. Linux线程同步(三)---互斥锁源码分析

    先给自己打个广告,本人的微信公众号:嵌入式Linux江湖,主要关注嵌入式软件开发,股票基金定投,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题. 一 源码分析 1.li ...

  8. linux之多任务的同步与互斥

    1.操作系统: 基本都是多任务操作系统,即同时有大量可调度实体在运行.在多任务操作系统中. 2.同时运行的多个任务可能产生的问题 1) 都需要访问/使用同一种资源           2) 多个任务之 ...

  9. Linux系统编程——多任务的同步与互斥

    现代操作系统基本都是多任务操作系统,即同时有大量可调度实体在运行.在多任务操作系统中,同时运行的多个任务可能: 都需要访问/使用同一种资源 多个任务之间有依赖关系,某个任务的运行依赖于另一个任务 这两 ...

  10. linux 内核互斥体,Linux 内核同步(六):互斥体(mutex)

    互斥体 互斥体是一种睡眠锁,他是一种简单的睡眠锁,其行为和 count 为 1 的信号量类似.(关于信号量参考:Linux 内核同步(四):信号量 semaphore). 互斥体简洁高效,但是相比信号 ...

最新文章

  1. 利用BIOS 中断INT 0x10显示字符和字符串
  2. python二十九:文件夹,包
  3. android热更新插件,与Android热更新方案Amigo的再次接触
  4. 用shell写了一个自动编译代码的脚本
  5. 如何切换默认python版本_Debian中如何切换默认Python版本
  6. 管理类软件设计“渔”之演化
  7. 蜘蛛牌 HDU - 1584(搜索——达到先让某些段先结合,达最优解)
  8. webflux 对url参数的接收处理
  9. html vba 单元格 格式,VBA设置单元格格式之——字体
  10. 多个Email的JS检测正刚表达式.
  11. U811.1接口EAI系列之二-BOM构成-委外BOM构成--VB语言
  12. mac电脑的磁盘空间变得越来越小
  13. 【个人笔记】OpenCV4 C++ 图像处理与视频分析 04课
  14. flash cs4 和 flex builder 联合开发
  15. 计算机语言 指令,计算机BASIC语言    指令
  16. app 显示未验证应用解决
  17. win10卸载软件_一款适合于windows端的卸载神器 彻底清理残留软件
  18. 多源异构数据整合在多规合一中的应用
  19. visual studio怎么让button一直生效_异地投保怎么做?看完你就知道
  20. audio codec简介

热门文章

  1. 视频来了 | 基于结构光投影三维重建技术系列课程
  2. 深度学习在计算机视觉领域(包括图像,视频,3-D点云,深度图)的应用一览
  3. 3D视觉应用研发系列笔记——机器人3D互动(一.技术难点分析)
  4. 机器学习入门书籍、课程推荐
  5. LaTeX 中表格的用法总结(四)——三线表和复杂的表格
  6. Android测试原理概述(一)
  7. 生物信息培训之WGCNA-权重基因共表达网络分析
  8. 束文圣和黄立南Nature综述极端环境中的微生物多样性
  9. ISME:长期进化实验揭示脱硫弧菌的硝酸盐耐受机制
  10. Microbiome:揩老鼠皮毛揩来高分文章——野生哺乳动物的皮肤和肠道微生物对核污染的反应...