理解EnterCriticalSection 临界区
通俗解释就像上厕所:
门锁了,就等着,等到别人出来了,进去锁上,然后该干什么干什么,干完了,把门打开
门没锁,就进去,锁上,然后该干什么干什么,干完了,把门打开
--------------------------------------------------
多线程中用来确保同一时刻只有一个线程操作被保护的数据
InitializeCriticalSection( cs);//初始化临界区
EnterCriticalSection( cs);//进入临界区
//操作数据
MyMoney*=10;//所有访问MyMoney变量的程序都需要这样写Enter.. Leave...
LeaveCriticalSection( cs);//离开临界区
DeleteCriticalSection( cs);//删除临界区
多个线程操作相同的数据时,一般是需要按顺序访问的,否则会引导数据错乱,无法控制数据,变成随机变量。为解决这个问题,就需要引入互斥变量,让每个线程都按顺序地访问变量。这样就需要使用EnterCriticalSection和LeaveCriticalSection函数。
比如说我们定义了一个共享资源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,就以此类推。
多线程死锁的产生以及如何避免死锁 指多个线程因竞争资源而造成的一种僵局(互相等待),具体代码就是同步中嵌套了其他同步,这种现象称为死锁:比如过独木桥问题,其他锁还有可重入锁、可中断锁、公平锁和同步锁
详解线程的信号量和互斥锁 前言:有个问题感觉一直会被问道:进程和线程的区别?也许之前我会回答: 进程:资源分配最小单位 线程:轻量级的进程 是系统调度的最小单位 由进程创建 多个线程共享进程的资源 但是现在我觉得一个比喻回答的更好:程序就像静止的火车,进程是运行的火车,线程是运行火车的每节车厢。
相关文章
- ERNIE-Doc自己的理解
- web安全day44:进阶,使用Nmap+Wireshark理解端口扫描
- php中的钩子理解及应用
- 浅理解扁平数据结构转Tree(树形结构)
- (二)STM32中中断优先级理解
- 《无线网络:理解和应对互联网环境下网络互连所带来的挑战》——1.7 蜂窝网络技术概述
- [UWP 自定义控件]了解模板化控件(2.1):理解ContentControl
- 【MySQL进阶-10】深入理解redolog,undolog和binlog的底层原理
- 如何理解js
- 《OpenStack实战》——1.2 理解云计算和OpenStack
- 机器学习中正则化项L1和L2的直观理解
- CA证书理解?CA证书的作用?
- js闭包的理解
- 面试突击(三)——理解计算机网络编程技术的复杂性
- 深入理解Vue组件3大核心概念
- 理解Promise (2)