第二部分:用户区同步

同步和互斥

  • 同步:就是按照一定的顺序执行不同的线程

  • 互斥:当一个线程访问某一资源的时候,其它线程不能同时访问

多线程产生的问题

#include <stdio.h>
#include <windows.h>

// 全局变量,被不同的线程访问和修改
int g_Number = ;

DWORD WINAPI ThreadPro1(LPVOID lpThreadParameter)
{
// 为 g_Number 自增 100000 次
for (int i = ; i < ; i++)
g_Number++;
return ;
}
DWORD WINAPI ThreadPro2(LPVOID lpThreadParameter)
{
// 为 g_Number 自增 100000 次
for (int i = ; i < ; i++)
g_Number++;
return ;
}
int main()
{
// 创建两个线程
HANDLE hThread1 = CreateThread(NULL, NULL, ThreadPro1, NULL, NULL, NULL);
HANDLE hThread2 = CreateThread(NULL, NULL, ThreadPro2, NULL, NULL, NULL);

// 等待两个线程执行结束
WaitForSingleObject(hThread1, -);
WaitForSingleObject(hThread2, -);

// 输出修改后的全局变量
printf("%d", g_Number);

return ;
}

产生问题的原因

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 = ; i < ; i++)
{
// 使用原子操作函数,将自增操作变为不可分割的一条指令
InterlockedIncrement(&g_Number);

// 以上语句会被翻译成下列单条汇编指令
// lock inc dword ptr [g_Number]
}

临界区(CriticalSection)

  • 特点:拥有线程拥有者的概念,同一个线程可以不断的重新进入临界区,但是进入了多少次,就要退出多少。

  • 缺点:一旦拥有临界区的线程崩溃,那么所有等待临界区的线程就会产生死锁。

  • 函数:

    • 初始化: InitializeCriticalSection

    • 保护:EnterCriticalSection

    • 结束保护 :LeaveCriticalSection

    • 删除:DeleteCriticalSection

// 1. 创建一个临界区(关键段)结构体
CRITICAL_SECTION CriticalSection = { };

// 2. 在 【main】 函数中对创建的临界区进行初始化操作
// InitializeCriticalSection(&CriticalSection);

DWORD WINAPI ThreadPro1(LPVOID lpThreadParameter)
{
// 为 g_Number 自增 100000 次
for (int i = ; i < ; i++)
{
// 当有一个线程正在执行代码的时候

// 同一个线程每进入一次受保护的区域,RecursionCount +1
// OwningThread 当前被哪一个线程所有

// 3. 使用 EnterCriticalSection 标识需要保护的代码的起始位置
EnterCriticalSection(&CriticalSection);
g_Number++;
// 4. 使用 LeaveCriticalSection 标识需要保护的代码的结束位置
LeaveCriticalSection(&CriticalSection);
}
return ;
}

Windows提高_2.2第二部分:用户区同步的更多相关文章

  1. Windows提高_2.3第三部分:内核区同步

    第三部分:内核区同步 等待函数(WaitForObject) 等待函数的形式 单个:WaitForSingleObject 多个:WaitForMultipleObjects 一个可以被等待的对象通常 ...

  2. Windows提高_2.1第一部分:线程

    第一部分:线程 什么是线程? 线程其实可以理解为一段正在执行中的代码,它最少由一个线程内核对象和一个栈组成. 线程之间是没有从属关系的,同一进程下的所有线程都可以访问进程内的所有内容. 主线程其实是创 ...

  3. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  4. Windows 下目录及文件向Linux同步

    本文解决的是Windows 下目录及文件向Linux同步的问题,Windows向 Windows同步的请参考:http://www.idcfree.com/article-852-1.html 环境介 ...

  5. linux/windows系统oracle数据库简单冷备同步

    linux/windows系统oracle数据库简单冷备同步 我们有一个财务系统比较看重财务数据的安全性,同时我们拥有两套系统,一个生产环境(linux),一个应急备份环境(windows).备份环境 ...

  6. 牛客网NOIP赛前集训营-普及组(第二场)和 牛客网NOIP赛前集训营-提高组(第二场)解题报告

    目录 牛客网NOIP赛前集训营-普及组(第二场) A 你好诶加币 B 最后一次 C 选择颜色 D 合法括号序列 牛客网NOIP赛前集训营-提高组(第二场) A 方差 B 分糖果 C 集合划分 牛客网N ...

  7. ftp客户端自动同步 Windows系统简单操作ftp客户端自动同步

    服务器管理工具它是一款功能强大的服务器集成管理器,包含win系统和linux系统的批量连接,vnc客户端,ftp客户端等等实用功能.我们可以使用这款软件的ftp客户端定时上传下载的功能来进实现ftp客 ...

  8. Windows与Linux之间的文件自动同步

    问题:在工作中遇到一个场景,需要每天定时将Linux机器上的文件自动同步到Windows机器上. 解决方案有两个: 1.在Windows 机器上设置共享目录,然后在Linux机器上挂载共享 目录,每天 ...

  9. windows环境利用semophore机制进行线程同步

    semophore是信号量的意思,常用于PV操作,所谓PV操作就是pend(等待,直到有资源可用,并且消耗资源) V就是释放资源. semophore和mutex区别,mutex本意为互斥,用于线程独 ...

随机推荐

  1. Android GMS无法通过网络定位

    前言          欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载.但请保留文章原始出处:          CSDN:http://www.csdn.net        ...

  2. TypeError: db.addUser is not a function : @(shell):1:1 ——mongoDB创建新用户名密码的方法

    不多说,旧版本使用 db.addUser("root","root") 新版本使用这句会出现这个错误提示 TypeError: db.addUser is no ...

  3. Android MaoZhuaWeiBo开发Service抓取个人信息-2

    前面把基本的东西讲完了,之后就是数据的获取和解析显示出来了,那接下来我们就负责抓取数据的这块吧,首先我们须要 在清单文件中载入服务和活动 加入:. <activity android:name= ...

  4. iOS开发——基础篇——get和post请求的区别

    HTTP 定义了与服务器交互的不同方法,最常用的有4种,Get.Post.Put.Delete,如果我换一下顺序就好记了,Put(增),Delete(删),Post(改),Get(查),即增删改查,下 ...

  5. 有意思的RTL函数RegisterClass(在持久化中,你生成的一个新类的对象,系统并不知道他是如何来的,因此需要你注册)good

    例子1:Delphi中使用纯正的面向对象方法(这个例子最直接) Delphi的VCL技术使很多程序员能够非常快速的入门:程序员门只要简单的拖动再加上少量的几个Pascal语句,呵呵,一个可以运行得非常 ...

  6. spring 之 IOC 依赖注入详解

    当我们对一个javaBean进行实例化时,在原本的情况下我们会选择新建一个接口,然后进行实例化,为了进一步降低耦合度我们还会使用工厂模式进行封装. 例: 当我们想要去造,Chinese.America ...

  7. 修改spring boot 启动logo

    修改spring boot 启动logo 在项目添加文件banner.txt,将需要的logo写在里面 效果:

  8. nginx目录列表和目录访问权限设置

    1.目录列表(directory listing) nginx让目录中的文件以列表的形式展现只需要一条指令 autoindex on; autoindex可以放在location中,只对当前locat ...

  9. python3 批量管理Linux服务器 下发命令与传输文件

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- import paramiko import os, stat import sys import ope ...

  10. 近年来火热的人工智能,其实是IT业界的一个障眼法

    近年来火热的人工智能,其实是IT业界的一个障眼法,仗着现在的计算机的计算能力牛B,把一个类仿生统计算法,宣传成了人工智能,不得不感叹一些营销人士的牛逼,说大话不腰疼.当然谎言重复一千遍也许自己也就信了 ...