在编程中常遇到这样的问题,线程A、B都需要用到数据Data。如线程A是用于写数据(Write)而线程B是用于读数据(Read)。一般而言这两个线程是互斥的,要不就读要不就是写。如果A线程还在运行时,B线程突然醒来,那么必然出现Data文件被占用的情况。为了避免这样的事情,我们就需要对数据进行“保护”。即在它被某个线程占用的时候,另外一个线程是不能访问它的,可以理解成让线程排队等候。EnterCriticalSection 和 LeaveCriticalSection就是现在要讲的函数,它们能做到以上所说的要求。

函数 EnterCriticalSection 声明如下:

WINBASEAPI

VOID

WINAPI

EnterCriticalSection(

__inoutLPCRITICAL_SECTION lpCriticalSection

);

LeaveCriticalSection类似,更简单的说这两个函数是用来确保同一时刻,只有一个线程对被保护的数据进行操作。相关的多线程数据函数还有

InitializeCriticalSection(&cs);//初始化临界区

EnterCriticalSection(&cs);//进入临界区

//操作数据()

MyMoney = 10;//所有访问MytMoney变量的进程都需要这样些Enter.. Leave...

LeaveCriticalSection(&cs);//离开临界区

DeleteCriticalSection(&cs);//删除临界区

比如说我们定义了一个共享资源dwTime[100],两个线程ThreadFuncA和ThreadFuncB都对它进行读写操作。当我们想要保证 dwTime[100]的操作完整性,即不希望写到一半的数据被另一个线程读取,那么用CRITICAL_SECTION来进行线程同步如下:
第一个线程函数:
DWORD WINAPI ThreadFuncA(LPVOID lp)
{
EnterCriticalSection(&cs);
...
// 操作dwTime
...
LeaveCriticalSection(&cs);
return 0;
}
写出这个函数之后,很多初学者都会错误地以为,此时cs对dwTime进行了锁定操作,dwTime处于cs的保护之中。一个“自然而然”的想法就是——cs和dwTime一一对应上了。
这么想,就大错特错了。dwTime并没有和任何东西对应,它仍然是任何其它线程都可以访问的。如果你像如下的方式来写第二个线程,那么就会有问题:
DWORD WINAPI ThreadFuncB(LPVOID lp)
{
...
// 操作dwTime
...
return 0;
}
当线程ThreadFuncA执行了EnterCriticalSection(&cs),并开始操作dwTime[100]的时候,线程 ThreadFuncB可能随时醒过来,也开始操作dwTime[100],这样,dwTime[100]中的数据就被破坏了。
为了让CRITICAL_SECTION发挥作用,我们必须在访问dwTime的任何一个地方都加上 EnterCriticalSection(&cs)和LeaveCriticalSection(&cs)语句。所以,必须按照下面的 方式来写第二个线程函数:
DWORD WINAPI ThreadFuncB(LPVOID lp)
{
EnterCriticalSection(&cs);
...
// 操作dwTime
...
LeaveCriticalSection(&cs);
return 0;
}
这样,当线程ThreadFuncB醒过来时,它遇到的第一个语句是EnterCriticalSection(&cs),这个语句将对cs变量 进行访问。如果这个时候第一个线程仍然在操作dwTime[100],cs变量中包含的值将告诉第二个线程,已有其它线程占用了cs。因此,第二个线程的 EnterCriticalSection(&cs)语句将不会返回,而处于挂起等待状态。直到第一个线程执行了 LeaveCriticalSection(&cs),第二个线程的EnterCriticalSection(&cs)语句才会返回, 并且继续执行下面的操作。
这个过程实际上是通过限制有且只有一个函数进入CriticalSection变量来实现代码段同步的。简单地说,对于同一个 CRITICAL_SECTION,当一个线程执行了EnterCriticalSection而没有执行LeaveCriticalSection的时 候,其它任何一个线程都无法完全执行EnterCriticalSection而不得不处于等待状态。
再次强调一次,没有任何资源被“锁定”,CRITICAL_SECTION这个东东不是针对于资源的,而是针对于不同线程间的代码段的!我们能够用它来进 行所谓资源的“锁定”,其实是因为我们在任何访问共享资源的地方都加入了EnterCriticalSection和 LeaveCriticalSection语句,使得同一时间只能够有一个线程的代码段访问到该共享资源而已(其它想访问该资源的代码段不得不等待)。
这就是使用一个CRITICAL_SECTION时的情况。你应该要知道,它并没有什么可以同步的资源的“集合”。这个概念不正确。如果是两个CRITICAL_SECTION,就以此类推。

EnterCriticalSection 多线程操作相同数据遇到的问题(线程锁)相关推荐

  1. 史上最强多线程面试44题和答案:线程锁+线程池+线程同步等

    最全BAT必考题答案系列 最全MySQL面试60题和答案 史上最全Spring面试71题与答案 史上最全Redis面试49题(含答案):哨兵+复制+事务+集群+持久化等 分布式缓存Redis+Memc ...

  2. Core Data 多线程操作实战篇

    最近在解决百度音乐iPhone客户端偶现数据库操作crash的问题,顺手整理了下CoreData的多线程原则,以及实际开发时应该如何遵守这些原则. Core Data多线程操作的基本原则 不允许跨线程 ...

  3. 多线程并发安全问题与线程锁

    一.多线程并发安全问题 二.什么是线程锁及分类 三.synchronized关键字 多线程并发安全问题 当多个线程并发操作同一临界资源,由于线程切换时机不确定,导致操作临界资源的顺序出现混乱严重时可能 ...

  4. Java多线程:多线程同步安全问题的 “三“ 种处理方式 ||多线程 ”死锁“ 的避免 || 单例模式”懒汉式“的线程同步安全问题

    Java多线程:多线程同步安全问题的 "三" 种处理方式 ||多线程 "死锁" 的避免 || 单例模式"懒汉式"的线程同步安全问题 每博一文 ...

  5. python多线程读取数据库数据_python多线程操作MySQL数据库pymysql

    python多线程操作MySQL数据库pymysql 项目中使用多线程操作数据库提示错误:pymysql.err.InterfaceError: (0, "),原因是pymysql的exec ...

  6. 基于人脸识别的课堂签到管理系统(四)---摄像头上传实时数据,百度AI读取并返回信息以及多线程操作

    基于人脸识别的课堂签到管理系统(四)---摄像头上传实时数据,百度AI读取并返回以及多线程操作 一. 前言概述 二.摄像头上传数据,读取百度AI返回信息 三.多线程操作 四.程序展示 五.相关下载 一 ...

  7. 多线程操作数据库时为了防止数据的增删改的混乱该在数据库层还是程序层面上进行同步?

    多线程操作数据库时为了防止数据的增删改的混乱该在数据库层还是程序层面上进行同步? [问题点数:60分,结帖人jiao_zg] 不显示删除回复 显示所有回复 显示星级回复 显示得分回复 只显示楼主 收藏 ...

  8. python多线程读取数据库数据_Python基于多线程操作数据库相关知识点详解

    Python基于多线程操作数据库相关问题分析 本文实例分析了Python多线程操作数据库相关问题.分享给大家供大家参考,具体如下: python多线程并发操作数据库,会存在链接数据库超时.数据库连接丢 ...

  9. FMDatabaseQueue 数据库多线程操作、事务处理

    SQLite数据库多线程操作: 在上面一节中已经讲过FMDB的用法了,接下来讲讲sqlite在都线程中的用法.如果应用中使用了多线程操作数据库,那么就需要使用FMDatabaseQueue来保证线程安 ...

最新文章

  1. Android --- RecyclerViwe中使用SnapHelper报错:“An instance of OnFlingListener already set.”
  2. 通过ribbon 根据服务名获取所有服务实例的IP和端口列表
  3. c++设计模式编程基础
  4. 使用boost.python进行混合开发
  5. python输入数据爬取_python根据用户需求输入想爬取的内容及页数爬取图片方法详解...
  6. 第四十一期:深度解析5G核心网建设难点和挑战
  7. 关于单片机串口发送和接收的问题
  8. 多线程知识梳理(2) - 并发编程的艺术笔记
  9. 全文搜索引擎 Elasticsearch 入门(ik,kibana,x-pack)
  10. 生活随笔:师弟,加油
  11. python的程序变量名_python中变量的名称和程序效率
  12. CCS 软件使用经验四则
  13. 修改电脑QQ界面大小
  14. 第二课:基于树莓派的10个经典项目(树莓派能做什么)
  15. 很好的--张量(Tensor)的技术以及它在不同场景中的应用--转载贪心科技
  16. Springboot访问静态页面
  17. Linux——例行性工作排程
  18. The Derivation About CNN and Antoencoder
  19. 用户运营:如何用B端运营思维做用户增长?
  20. 索骥馆-走向世界之《用美国小孩的方法学英文动词》扫描版[PDF]

热门文章

  1. Unity3D基础1:进入Unity3D
  2. Project Euler 628: Open chess positions(公式)
  3. bzoj 1603: [Usaco2008 Oct]打谷机(拆点并查集)
  4. virtualenv虚拟独立python环境使用
  5. 四分之一波长阻抗变换器
  6. linux 线程异常退出_Linux 进程必知必会
  7. PHP 数据库中的模糊查询
  8. 销售订单获取不到即时库存
  9. 【题解】ZJOI2017仙人掌
  10. Linux操作系统下的多线程编程详细解析----条件变量