Windows提高_2.2第二部分:用户区同步
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Windows提高_2.2第二部分:用户区同步,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3264字,纯文字阅读大概需要5分钟。
内容图文
第二部分:用户区同步
同步和互斥
-
同步:就是按照一定的顺序执行不同的线程
-
互斥:当一个线程访问某一资源的时候,其它线程不能同时访问
多线程产生的问题
#include <stdio.h> #include <windows.h> ? // 全局变量,被不同的线程访问和修改 int g_Number = 0; ? DWORD WINAPI ThreadPro1(LPVOID lpThreadParameter) { // 为 g_Number 自增 100000 次 for (int i = 0; i < 100000; i++) g_Number++; return 0; } DWORD WINAPI ThreadPro2(LPVOID lpThreadParameter) { // 为 g_Number 自增 100000 次 for (int i = 0; i < 100000; i++) g_Number++; return 0; } int main() { // 创建两个线程 HANDLE hThread1 = CreateThread(NULL, NULL, ThreadPro1, NULL, NULL, NULL); HANDLE hThread2 = CreateThread(NULL, NULL, ThreadPro2, NULL, NULL, NULL); ? // 等待两个线程执行结束 WaitForSingleObject(hThread1, -1); WaitForSingleObject(hThread2, -1); ? // 输出修改后的全局变量 printf("%d", g_Number); ? return 0; }
产生问题的原因
mov eax, dword ptr[Number]
add eax, 1
mov dword ptr[Number],eax
; C语言的单条语句被翻译成了多条汇编代码,二线程的切换可能导致多条代码分开执行
mov eax, dword ptr[Number] [0]: Number(0) eax(0)
add eax, 1 [0]: Number(0) eax(1)
mov dword ptr[Number],eax [0]: Number(1) eax(1)
?
mov eax, dword ptr[Number] [1]: Number(1) eax(1)
add eax, 1 [1]: Number(1) eax(2)
mov dword ptr[Number],eax [1]: Number(2) eax(1)
?
mov eax, dword ptr[Number] [0]: Number(2) eax(2)
add eax, 1 [0]: Number(2) eax(3) -----------
?
mov eax, dword ptr[Number] [1]: Number(2) eax(2)
add eax, 1 [1]: Number(2) eax(3)
mov dword ptr[Number],eax [1]: Number(3) eax(3)
mov eax, dword ptr[Number] [1]: Number(3) eax(3)
add eax, 1 [1]: Number(3) eax(4)
mov dword ptr[Number],eax [1]: Number(4) eax(4)
?
mov dword ptr[Number],eax [0]: Number(3) eax(3) -----------
原子操作(Interlocked...)
-
特点:将一条语句转换成了具有同等功能的单条汇编指令
lock inc dword ptr [Number]
-
缺点:只能给单个整数类型(4/8)进行保护,不能给使一段代码变成原子操作
-
函数:
-
InterlockedXXX
-
for (int i = 0; i < 100000; i++) { // 使用原子操作函数,将自增操作变为不可分割的一条指令 InterlockedIncrement(&g_Number); ? // 以上语句会被翻译成下列单条汇编指令 // lock inc dword ptr [g_Number] }
临界区(CriticalSection)
-
特点:拥有线程拥有者的概念,同一个线程可以不断的重新进入临界区,但是进入了多少次,就要退出多少。
-
缺点:一旦拥有临界区的线程崩溃,那么所有等待临界区的线程就会产生死锁。
-
函数:
-
初始化: InitializeCriticalSection
-
保护:EnterCriticalSection
-
结束保护 :LeaveCriticalSection
-
删除:DeleteCriticalSection
-
// 1. 创建一个临界区(关键段)结构体 CRITICAL_SECTION CriticalSection = { 0 }; ? // 2. 在 【main】 函数中对创建的临界区进行初始化操作 // InitializeCriticalSection(&CriticalSection); ? DWORD WINAPI ThreadPro1(LPVOID lpThreadParameter) { // 为 g_Number 自增 100000 次 for (int i = 0; i < 100000; i++) { // 当有一个线程正在执行代码的时候 ? // 同一个线程每进入一次受保护的区域,RecursionCount +1 // OwningThread 当前被哪一个线程所有 ? // 3. 使用 EnterCriticalSection 标识需要保护的代码的起始位置 EnterCriticalSection(&CriticalSection); g_Number++; // 4. 使用 LeaveCriticalSection 标识需要保护的代码的结束位置 LeaveCriticalSection(&CriticalSection); } return 0; }
内容总结
以上是互联网集市为您收集整理的Windows提高_2.2第二部分:用户区同步全部内容,希望文章能够帮你解决Windows提高_2.2第二部分:用户区同步所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。