写点什么

计算机操作系统基础 (十一)--- 线程同步之互斥量

用户头像
书旅
关注
发布于: 2020 年 07 月 04 日
计算机操作系统基础(十一)---线程同步之互斥量

引言

本文为第十一篇,线程同步之互斥量,在前边的《计算机操作系统基础(四)---进程管理之进程同步》中提到了进程同步和线程同步的方法,本篇为线程同步方法之一---互斥量。建议重新回顾一下《计算机操作系统基础(四)---进程管理之进程同步》这篇文章,方便理解后边的几篇关于线程同步和进程同步的知识



互斥量

在进程同步的那篇文章中有介绍到生产者和消费者模型,该模型中有两个线程,分别充当生产者和消费者的角色,在并发的情况下,这两个线程很有可能同时去操作临界资源,如果同时去操作临界资源就有可能造成线程同步的问题,互斥量就是解决线程同步的方法之一



互斥量是如何解决这种问题的?



互斥量是保证当某一个线程,比如说线程1在操作临界资源时,它就可以阻止其它线程访问临界资源,这个就是互斥量的工作原理





在前边的生产者和消费者模型中,引发线程同步的最根本原因其实就是:这两个线程的指令交叉执行,互斥量可以保证两个线程的指令不会交叉的执行





其实互斥量的效果也称为原子性,互斥量其实就是保证了这些关键指令的原子性。原子性就是:

  • 原子性是指一系列操作不可中断的特性

  • 这一系列操作要么全部执行完成,要么全部没有执行

  • 不存在部分执行,部分未执行的情况



就比如刚才的生产者的操作,生产者的操作分为三条指令,根据原子性的特性,这三条指令要么全部执行完成,要么全部未执行,不存在说执行了其中的一条或两条时CPU被抢走了



  • 互斥量是最简单的线程同步方法

  • 互斥量(互斥锁),处于两种状态之一的变量:解锁和*加锁*

  • 两个状态可以保证资源访问的串行(如果说一个资源被加锁了,也就是这个资源被某一个线程所使用了,另外一个线程如果想使用这个资源的话,只能等待正在使用这个资源的线程释放资源,另外一个线程才可以使用这个资源,这样就保证了资源访问的串行)



互斥锁的代码示例



未使用互斥量

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
$include<vector>

//临界资源
int num=0;

//生产者
void *producer(void*){
int times = 100000000;//循环一百万次
while(times--){
num += 1;//每次生产一个产品
}
}

//消费者
void *comsumer(void*){
int times = 100000000;
while(times--){
num -= 1;//每次消费一个产品
}
}

int main()
{
printf("Start in main function.");
//定义两个线程
pthread_t thread1,thread2;
//一个执行生成者逻辑,一个执行消费者逻辑
pthread_create(&thread1, NULL, &producer, NULL);
pthread_create(&thread2, NULL, &comsumer, NULL);
pthread_join(&thread1, NULL);
pthread_join(&thread2, NULL);
//打印临界资源的值
printf("Print in main function: num = %d\n", num);
}

运行结果:





虽然生产者和消费者循环的次数都是一样的,但是num的运行结果却不是0,这就存在生产者和消费者问题。通过互斥量来解决这个问题



使用互斥量

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
$include<vector>

//初始化互斥量
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

//临界资源
int num=0;

//生产者
void *producer(void*){
int times = 100000000;//循环一百万次
while(times--){
//加锁
pthread_mutex_lock(&mutex);
num += 1;//每次生产一个产品
//解锁
pthread_mutex_unlock(&mutex);
}
}

//消费者
void *comsumer(void*){
int times = 100000000;
while(times--){
//加锁
pthread_mutex_lock(&mutex);
num -= 1;//每次消费一个产品
//解锁
pthread_mutex_unlock(&mutex);
}
}

int main()
{
printf("Start in main function.");
//定义两个线程
pthread_t thread1,thread2;
//一个执行生成者逻辑,一个执行消费者逻辑
pthread_create(&thread1, NULL, &producer, NULL);
pthread_create(&thread2, NULL, &comsumer, NULL);
pthread_join(&thread1, NULL);
pthread_join(&thread2, NULL);
//打印临界资源的值
printf("Print in main function: num = %d\n", num);
}

运行结果:





结果是0,说明加互斥量是有作用的。加锁之后其实会发现代码的执行时间会变长,这是因为加锁会带来性能的损耗



这就是互斥量的内容,示例是使用C语言进行编写,各种语言中也都有提供互斥量的API,PHP的互斥量API可参见这里:https://www.php.net/mutex



在快速变化的技术中寻找不变,才是一个技术人的核心竞争力。知行合一,理论结合实践





发布于: 2020 年 07 月 04 日阅读数: 56
用户头像

书旅

关注

公众号:IT猿圈 2019.04.11 加入

还未添加个人简介

评论

发布
暂无评论
计算机操作系统基础(十一)---线程同步之互斥量