在我们上一章节学习了多线程,我们可以得知在一个进程里,主控线程,与多个子线程共享资源(比如全局变量),但是,我们发现有弊端,它们都可以修改共享资源里面的数据,并且运行 无先后顺序。

因此、同步和互斥就是用于解决这两个问题的。

一、什么是同步、什么是互斥?

互斥:
    
  一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源。具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

同步:
       
两个或两个以上的进程或线程在运行过程中协同步调,按预定的先后次序运行。

同步就是在互斥的基础上有顺序 。

POSIX标准中进程和线程同步和互斥的方法,主要有信号量和互斥锁两种方式。

二、互斥锁

2.1互斥锁的概念

mutex是一种简单的加锁的方法来控制对共享资源的访问,mutex只有两种状态,

上锁(lock)解锁(unlock)

在访问该资源前,首先应申请mutex,

如果mutex处于unlock状态,则会申请到mutex并立即lock;
       如果mutex处于lock状态,则默认阻塞申请者。
  unlock(解锁)操作应该由lock者进行。

2.2互斥锁的操作

第一步:初始化互斥锁

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

初始化互斥锁有两个种方法:

一种静态分配互斥锁

一种动态分配互斥锁(常用

1) 静态分配的互斥锁:
          pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
2)动态分配互斥锁(常用):
          pthread_mutex_t mutex;
          pthread_mutex_init(&mutex, NULL);

在所有使用过此互斥锁的线程都不再需要使用时候,应调用pthread_mutex_destroy销毁
互斥锁

三、互斥锁各函数

3.1初始化互斥锁

头文件

#include <pthread.h>
函数

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
功能:

初始化一个互斥锁
参数:

mutex:指定的互斥锁
            mutexattr:互斥锁的属性,为NULL表示默认属性
 返回值:
              成功:0

3.2、互斥锁上锁(阻塞等待)常用

头文件:

#include <pthread.h>
函数:

int pthread_mutex_lock(pthread_mutex_t *mutex);
功能:

对互斥锁上锁,若已经上锁,则调用者一直阻塞到互斥锁解锁
参数:
            mutex:指定的互斥锁
返回值:

成功:0
            失败:非0

3.3 互斥锁上锁(非阻塞等待)只需了解

头文件:

#include <pthread.h>
函数:

int pthread_mutex_trylock(pthread_mutex_t *mutex);
功能:

对互斥锁上锁,若已经上锁,则上锁失败,函数立即返回。
参数:
            mutex:互斥锁地址。
返回值:
           成功:0
           失败:非0

3.4、互斥锁解锁

头文件

#include <pthread.h>
函数:

int pthread_mutex_unlock(pthread_mutex_t * mutex);
功能:

对指定的互斥锁解锁。
参数:
             mutex:互斥锁地址。
返回值:
             成功:0
             失败:非0

3.5、销毁互斥锁

头文件

#include <pthread.h>
函数:

int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能:

销毁指定的一个互斥锁。
参数:
            mutex:互斥锁地址。
返回值:

成功:0
              失败:非0。

四、案例:有两张银行卡,一张是主卡,另外一张副卡,都去取钱。

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include <unistd.h>int money=10000;      //卡一共有10000元pthread_mutex_t mymutex;void *pthread_fun1(void *arg)
{int getmoney;      //实际取的钱int yu_er;         //卡余额int withdraw=4800; //预先想取的钱数pthread_mutex_lock(&mymutex);printf("张三使用主卡去取钱 \n");sleep(1);printf("张三正在取钱 \n");if(money < withdraw){getmoney=0;yu_er =money;}else if(money >= withdraw){getmoney=withdraw;yu_er=money-withdraw;}      money = yu_er;sleep(1);printf("张三预先想取%d元 实际取了%d元 卡里余额%d元\n",withdraw,getmoney,yu_er);pthread_mutex_unlock(&mymutex);
}void *pthread_fun2(void *arg)
{int getmoney;       //实际取的钱int yu_er;          //卡余额int withdraw1=2800;  //预先想取的钱数pthread_mutex_lock(&mymutex);printf("李四使用副卡去取钱 \n");sleep(1);printf("李四正在取钱 \n");if(money < withdraw1){getmoney=0;yu_er =money;}else if(money >= withdraw1){getmoney=withdraw1;yu_er=money-withdraw1;}      money = yu_er;
sleep(1);
printf("李四预先想取 %d元 实际取了%d元 卡里余额%d元\n",withdraw1,getmoney,yu_er);pthread_mutex_unlock(&mymutex);
}
int main()
{ int ret1;int ret2;pthread_t pthread1;pthread_t pthread2;pthread_mutex_init(&mymutex,NULL);if((ret1=pthread_create(&pthread1,NULL,pthread_fun1,NULL))!=0){           perror("fail to pthread_create1");exit(1); }if((ret2=pthread_create(&pthread2,NULL,pthread_fun2,NULL))!=0){           perror("fail to pthread_create2");exit(1); } if(pthread_join(pthread1,NULL)!=0){perror("fail to pthread_join1");exit(1);}         if(pthread_join(pthread2,NULL)!=0){perror("fail to pthread_join2");exit(1);}pthread_mutex_destroy(&mymutex);return 0;}

运行结果

张三使用主卡去取钱 
张三正在取钱 
张三预先想取4800元 实际取了4800元 卡里余额5200元
李四使用副卡去取钱 
李四正在取钱 
李四预先想取 2800元 实际取了2800元 卡里余额2400元

互斥锁的使用(学习笔记)相关推荐

  1. MIT的学习资料(reading部分)锁与同步学习笔记

    MIT的学习资料(reading部分)锁与同步学习笔记 系统构件题材及问题探讨 锁和同步 目标 了解一个锁是用于保护共有的可变数据 能够认识到的僵局以及知道战略,以防止它 知道监视器模式,并能够将其应 ...

  2. mysql悲观锁 更新_MySQL学习笔记(四)悲观锁 for update

    恼骚 最近在搞并发的问题,订单的异步通知和主动查询会存在并发的问题,用到了Mysql数据库的 for update 锁 在TP5直接通过lock(true),用于数据库的锁机制 Db::name('p ...

  3. java同步锁优化方案学习笔记(偏向锁,轻量级锁,自旋锁,重量级锁)

    目录 一,概述 二,CAS算法 三,Java对象的对象头,以及Mark Word 四,偏向锁 Baised Lock 五,轻量级锁 六,自旋锁 SpinLock 七,重量级锁 八,在应用层提高锁效率的 ...

  4. JUC.Condition学习笔记[附详细源码解析]

    JUC.Condition学习笔记[附详细源码解析] 目录 Condition的概念 大体实现流程 I.初始化状态 II.await()操作 III.signal()操作 3个主要方法 Conditi ...

  5. 学习笔记(19):Python网络编程并发编程-互斥锁

    立即学习:https://edu.csdn.net/course/play/24458/296430?utm_source=blogtoedu 1.互斥锁: 多进程间的内存是相互隔离的,因此其数据也是 ...

  6. 学习笔记(26):Python网络编程并发编程-GIL与自定义互斥锁的区别

    立即学习:https://edu.csdn.net/course/play/24458/296443?utm_source=blogtoedu 1.GIL的基本概念 答:GIL本质上就是一把锁,只是他 ...

  7. 学习笔记(20):Python网络编程并发编程-互斥锁与join的区别

    立即学习:https://edu.csdn.net/course/play/24458/296432?utm_source=blogtoedu 互斥锁与join的异同: 1.同:都是将多进程并发模式变 ...

  8. Go 学习笔记(23)— 并发(02)[竞争,锁资源,原子函数sync/atomic、互斥锁sync.Mutex]

    本文参考 <Go 语言实战> 1. 竞争状态简述 如果两个或者多个 goroutine 在没有互相同步的情况下,访问某个共享的资源,并试图同时读和写这个资源,就处于相互竞争的状态,这种情况 ...

  9. 进程通信学习笔记(互斥锁和条件变量)

    1.互斥锁:上锁和解锁 Posix互斥锁作为数据类型pthread_mutex_t的变量声明.如果互斥锁变量是静态分配的,那么可以把它初始化成常值PTHREAD_MUTEX_INITIALIZER.如 ...

最新文章

  1. Python高级特性(切片,迭代,列表生成式,生成器,迭代器)
  2. Windows ninja
  3. 前端一HTML:十三:css的三大特性
  4. Asp.net Core 使用Redis存储Session
  5. Go报错:more than one character in rune literal
  6. 第七章数组答案C语言,c语言复习题及答案第七章数组.docx
  7. 高德联手饿了么:外卖小哥跑出偏远地区活地图
  8. php switch正则表达式,switch的用法以及正则表达式简单的用法
  9. 怎么把文件上传云服务器上,如何把文件上传到云服务器上
  10. JS void运算符
  11. Grid使用 ComboBox Binding DateTime Format WPF
  12. 长假终结踏上归途 网络电话延续团圆亲情
  13. 并发与计算机体系结构
  14. Python更改pip镜像源
  15. 配置eclipse插件
  16. 广州地铁公厕(洗手间)和母婴室信息汇总
  17. 计算机中三大总线:地址总线、数据总线、控制总线
  18. Navicat 11 Premium中文破解版使用心得
  19. if while的用法
  20. 中国石油大学(北京)-《 修井工程》第二阶段在线作业

热门文章

  1. 最大似然估计,最大后验估计,贝叶斯估计联系与区别
  2. ps快捷图标在哪个文件夹_photoshop快捷键及快捷方式(详细)
  3. oracle中正则表达式规则,Oracle SQL 正则表达式
  4. paramiko的安装
  5. 单片机IO口控制12V电压通断,MOS和三极管电路
  6. Android 毕业设计高仿抖音(视频类App)(内附源码)
  7. C语言循环输出能被3整除的数
  8. 关于大数据的视频资料
  9. ntp网络时间服务器(网络时钟同步)客户端与服务器端设置方法说明
  10. rand和srand的用法