当前位置: 首页 > news >正文

【C语言】Windows下的多线程编程-原子操作

在计算机中,原子操作又称为原语,操作系统保证:原子操作是不可分割的,在执行完毕之前不会被任何其它任务或事件中断。

下面列出一些常用的Interlocked系列函数:

InterlockedIncrement自增

/** \brief 	实现数的原子性自减** \param   lpAddend 指向要递增的变量的指针* \return  返回自增后的变量值**/
LONG InterlockedIncrement(LPLONG lpAddend);

在C中相当于

int i = 0;
i++;

为了保证原子性,应

InterlockedIncrement((long*)&i);

举个例子:如果一个变量 long value =0;
首先说一下正常情况下的加减操作:value+=1;
1:系统从Value的空间取出值,并动态生成一个空间来存储取出来的值;
2:将取出来的值和1作加法,并且将和放回Value的空间覆盖掉原值。加法结束。
如果此时有两个Thread ,分别记作threadA,threadB。
1:threadA将Value从存储空间取出,为0;
2:threadB将Value从存储空间取出,为0;
3:threadA将取出来的值和1作加法,并且将和放回Value的空间覆盖掉原值。加法结束,Value=1。
4:threadB将取出来的值和1作加法,并且将和放回Value的空间覆盖掉原值。加法结束,Value=1。
最后Value =1 ,而正确应该是2;这就是问题的所在,InterlockedIncrement能够保证在一个线程访问变量时其它线程不能访问。同理InterlockedDecrement。

InterlockedDecrement自减

/** \brief 	实现数的原子性自增** \param   lpAddend 指向要递减的变量的指针* \return  返回自减后的变量值**/
LONG InterlockedDecrement(LPLONG lpAddend);

在C中相当于

int i = 0;
i--;

为了保证原子性,应

InterlockedDecrement((long*)&i);

InterlockedExchangeAdd加减

/** \brief 	实现数的原子性自增** \param   Addend 指向要加减的变量的指针* \param   Increment 要加减的值* \return  返回变量值**/
LONG InterlockedExchangeAdd(LPLONG Addend, LONG Increment);

示例

InterlockedExchangeAdd((long*)&i, 5);//等价于 i = i + 5;

InterlockedExchange赋值

/** \brief 	实现数的原子性赋值** \param   Addend 指向要赋值的变量的指针* \param   Value 要加减的值* \return  返回变量值**/
LONG InterlockedExchange(LPLONG Addend, LONG Value);

示例

InterlockedExchange((long*)&i, 10);//等价于 i = 5;

示例

模拟用户登录(线程),登录一次则记录一次,最终输出有多少个用户登录的多少次。

#include <stdio.h>
#include <Windows.h>
#include <process.h>#define THREAD_COUNT 10U	//用户数void Thread(void*);volatile int count = 0;//记录登录的次数int main()
{HANDLE th[THREAD_COUNT] = { 0 };int num = 30;//模拟次数while (num--){count = 0;//重置登录次数for (size_t i = 0; i < THREAD_COUNT; i++){/* 创建线程 */th[i] = _beginthread(Thread, 0, NULL);}//等待所有线程结束WaitForMultipleObjects(THREAD_COUNT, th, TRUE, INFINITE);printf("共 %d 个用户  最终登录的次数为%d\n", THREAD_COUNT, count);}return 0;
}void Thread(void* arg)
{Sleep(100);count++;
}

输出结果
在这里插入图片描述

输出结果把变量自增操作封装为原子性操作

#include <stdio.h>
#include <Windows.h>
#include <process.h>#define THREAD_COUNT 10U	//用户数void Thread(void*);volatile int count = 0;//记录登录的次数int main()
{HANDLE th[THREAD_COUNT] = { 0 };int num = 30;//模拟次数while (num--){count = 0;//重置登录次数for (size_t i = 0; i < THREAD_COUNT; i++){/* 创建线程 */th[i] = _beginthread(Thread, 0, NULL);}//等待所有线程结束WaitForMultipleObjects(THREAD_COUNT, th, TRUE, INFINITE);printf("共 %d 个用户  最终登录的次数为%d\n", THREAD_COUNT, count);}return 0;
}void Thread(void* arg)
{Sleep(100);//count++;InterlockedIncrement((long*)&count);
}

输出结果
在这里插入图片描述

http://www.xdnf.cn/news/797599.html

相关文章:

  • 10个最好的照片分享网站
  • 1Checker(易改英文校对软件)官方中文版V2.0.1.5 | 易改英语单词检查软件下载
  • 如何使用Discuz搭建一个自己的论坛并实现无公网IP与云服务器异地访问
  • 关于【QQ空间魔力日志】的说明
  • 软件项目管理过程全套文档(开发#实施#运维#安全#交付)
  • 雨林木风 Ghost XP SP2 精简版 Y2.0
  • InCell屏幕是一种什么类型的屏幕?如何进行编程?
  • 可能是最详细的UMD模块入门指南,前端开发就业前景
  • GALGAME文字提取agth 特殊码大全(特殊码表)和使用方法
  • “IT小百科”之“Windows自带的服务和系统进程详解”
  • Linux kernel damon实现
  • ubuntu上python编辑器_Ubuntu中安装python编辑器Ulipad
  • 锦天科技被盛大收购 23岁创始人成亿万富翁
  • 看了去年这些最热的木马、病毒和电信诈骗,感觉今年不会被骗了
  • API Hook 原理
  • bt4破解教程
  • 怎么做手机App测试?app测试详细流程和方法介绍!
  • 2024国内氛围比较好的黑客论坛社区还有哪些?
  • 综合评价法之秩和比法(RSR)
  • 四枚硬币,摆成一个正方形,不知道硬币的正反面,盲翻必胜策略
  • 内容管理系统
  • cpu功能解析,cpu功能作用与其工作过程
  • 2023年最新qq空间说说怎么全部删除_QQ空间说说如何批量删除
  • 施一公:如何成为一名优秀的博士生?
  • 基于单片机出租车计价器原理图
  • 微软常用运行库合集32+64位合集 v2023.10.04
  • 传输层协议:网络通信的关键纽带
  • 菜鸟学习C++之Console Application
  • Java空间详解
  • Windows 批处理(bat)语法大全