一个简单案例理解为什么在多线程的应用中要使用互斥锁

news/2024/11/29 2:51:59/

需求:使用10个线程,同时对一个值count进行加一操作,每个线程对count加100000次,最终使得count=1000000

第一版代码:不加锁

​​​lock.c


#include<stdio.h>
#include<pthread.h>#define THREAD_COUNT 10void *thread_callback(void *arg){int *pcount=(int*)arg;int i=0;while(i++ < 100000){(*pcount)++;usleep(1);//休眠一毫秒}
}int main(){pthread_t threadid[THREAD_COUNT]={0};//定义多线程int i=0;int count=0;for(i=0;i<THREAD_COUNT;i++){pthread_create(&threadid[i],NULL,thread_callback,&count);}//每隔一秒打印一次count值for(i=0;i<100;i++){printf("count: %d\n",count);sleep(1);//休眠一秒}return 0; 
}

在Linux环境下编译执行:

编译:  gcc -o lock lock.c -pthread

执行: ./lock

运行结果:

 在不加锁的情况之下,使用多线程无法满足需求,即count值无法加到1000000. 

从代码分析唯一能改变count值得代码是:count++,源代码中为:(*pcount)++

count++转化为汇编语言为:

正常情况(预期情况):每一个线程的count++都执行完再执行另外一个线程的count++ 

eax:寄存器

不正常情况(实际情况):当前线程中count++没完全执行完就跳转到另外一个线程执行 

线程在执行代码的过程中被打断,这样所带来的的结果就是两个线程中执行两次count++,但count实际值只加了1,使得结果不能达到我们所预期的1000000值.

解决方法:加锁,使得每个线程在执行是不被打断,即不会出现不正常情况.

第二版代码:这里使用互斥锁(mutex),也可以使用自旋锁(spinlock)


#include<stdio.h>
#include<pthread.h>#define THREAD_COUNT 10pthread_mutex_t mutex;//定义一个锁void *thread_callback(void *arg){int *pcount=(int*)arg;int i=0;while(i++ < 100000){#if 0(*pcount)++;#elsepthread_mutex_lock(&mutex);//上锁(*pcount)++;pthread_mutex_unlock(&mutex);//解锁#endifusleep(1);//休眠一毫秒}
}int main(){pthread_t threadid[THREAD_COUNT]={0};//定义多线程pthread_mutex_init(&mutex,NULL);//初始化锁,NULL为系统默认int i=0;int count=0;for(i=0;i<THREAD_COUNT;i++){pthread_create(&threadid[i],NULL,thread_callback,&count);}for(i=0;i<100;i++){printf("count: %d\n",count);sleep(1);//休眠一秒}return 0; 
}

运行结果: 

 


http://www.ppmy.cn/news/551104.html

相关文章

文件系统概述

目录 概述用户空间层面1.应用程序可以直接使用内核提供的系统调用访问文件&#xff1a;2.应用程序也可以使用 glibc 库封装的标准 I/O 流函数访问文件&#xff1a; 硬件层面1.块设备2.闪存3.NVDIMM 内核空间层面 概述 在 Linux 系统中&#xff0c;一切皆文件&#xff0c;除了通…

【MySQL数据库】存储过程

目录 一、存储过程1.1概述1.2优点 二、存储过程实战2.1创建存储过程2.2存储过程的参数2.3条件语句 if-then-else end if2.4循环语句while end while 一、存储过程 1.1概述 存储过程是一组为了完成特定功能的SQL语句集合。存储过程在使用过程中是将常用或者复杂的工作预先使…

笔记本电量图表显示

step1&#xff1a;打开设置》设备管理器 step2&#xff1a;展开电池&#xff0c;对电池内的项目全部禁用后再启用

笔记本电脑上电量图标显示方法

记录一下笔记本电量小图标显示不出问题的解决方法&#xff1a; 1、打开设备管理器 找到“电池”下的两个子项 2、右键每个子项&#xff0c;选择“禁用设备”后再选择“启用设备”即可显示电池图标

C语言里面那些你必须知道的常用关键字(详细讲解)

前言 哈喽&#xff0c;各位铁汁们好啊&#xff01;✨今天来给大家带来的是C语言中我们常用的关键字静态static的详细讲解和typedef 、#define定义常量和宏。   既然是详解想必大家必定是想学一些平常学不到的东西吧&#xff01;这里博主给大家详细讲解static修饰的变量在内存…

基于灰色预测模型的负荷预测(matlab程序)

0.代码链接 基于灰色预测模型的负荷预测&#xff08;matlab程序&#xff09;资源-CSDN文库 1.简述 灰色预测是一种对含有不确定因素的系统进行预测的方法。灰色预测通过鉴别系统因素之间发展趋势的相异程度&#xff0c;即进行关联分析&#xff0c;并对原始数据进行生成处理来…

android 面试知识点

自我介绍&#xff1a; 您好&#xff0c;我是xxx&#xff0c;从事android开发也有好几年了&#xff0c;总共呆过两家公司&#xff0c;第一家是xx,干了1年&#xff0c;在这家公司做过3个项目&#xff0c;刚开始的时候主要写一些需求文档&#xff0c;用xmind整理项目功能&#xff…

阿里巴巴Java面试题

文章目录 一、基础篇1.1.Java语言有哪些特点1.2.面向对象和面向过程的区别1.3.八种基本数据类型的大小&#xff0c;以及他们的封装类1.4.标识符的命名规则。1.5.instanceof 关键字的作用1.6.Java自动装箱与拆箱1.7.重载和重写的区别1.8.equals与的区别1.9.Hashcode的作用1.10.S…