通俗解释就像上厕所:
门锁了,就等着,等到别人出来了,进去锁上,然后该干什么干什么,干完了,把门打开
门没锁,就进去,锁上,然后该干什么干什么,干完了,把门打开
--------------------------------------------------
多线程中用来确保同一时刻只有一个线程操作被保护的数据
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,就以此类推。
通俗解释就像上厕所:
门锁了,就等着,等到别人出来了,进去锁上,然后该干什么干什么,干完了,把门打开
门没锁,就进去,锁上,然后该干什么干什么,干完了,把门打开
--------------------------------------------------
多线程中用来确保同一时刻只有一个线程操作被保护的数据
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,就以此类推。
分享到:
相关推荐
2. `EnterCriticalSection()`:让当前线程进入临界区。如果临界区已经由另一个线程占有,那么调用线程将被阻塞,直到临界区变得可用。 3. `LeaveCriticalSection()`:让当前线程离开临界区。这个函数应该在线程完成...
调用`EnterCriticalSection`进入临界区,`LeaveCriticalSection`退出临界区。当一个线程在临界区内时,其他尝试进入的线程会被阻塞,直到当前线程离开临界区。 3. 最后,记得在不再需要临界区时进行清理: ```cpp ...
2. 进入临界区:使用`EnterCriticalSection()`函数,线程请求进入临界区。如果当前没有其他线程在临界区内,该线程将成功进入并开始执行临界区内的代码。如果有其他线程已经进入,那么当前线程会被挂起,直到其他...
首先,我们需要理解临界区的概念。临界区是一个代码段,其中包含对共享资源的访问。当一个线程进入临界区时,其他试图进入的线程将被阻塞,直到该线程离开临界区。在Delphi中,我们可以使用TCriticalSection对象来...
在Windows API中,可以使用`EnterCriticalSection`和`LeaveCriticalSection`函数来进入和退出临界区。这些函数会自动处理线程间的同步,确保一次只有一个线程能执行临界区内的代码。在C++标准库中,也有`std::mutex`...
在多线程编程中,确保线程安全是至关重要的,而线程临界区就是解决这一问题的关键技术之一。...通过理解和熟练运用线程临界区,开发者可以在VC++的多线程环境中构建出高效、可靠的程序,确保数据一致性,避免并发问题。
这个主题的核心是理解和实现线程临界区的有效管理,以确保系统的正确性和高效性。 在多线程编程中,多个线程可能同时运行,如果它们尝试修改同一份共享数据,可能会导致混乱的结果。例如,两个线程同时增加一个...
2. **进入临界区**:在需要保护的代码块之前,线程通过调用`EnterCriticalSection()`函数进入临界区。此时,其他尝试进入临界区的线程将被阻塞,直到当前线程退出临界区。 3. **执行关键操作**:在临界区内,线程...
临界区的实现通常依赖于操作系统提供的原语,如Windows下的`EnterCriticalSection`和`LeaveCriticalSection`,或者POSIX标准中的`pthread_mutex_lock`和`pthread_mutex_unlock`。这些函数使得线程在进入临界区前需要...
通过理解临界区的工作原理,并结合提供的"criticalsection_test"源码,开发者可以深入学习如何在实际项目中有效地实现线程同步,确保多线程程序的稳定和正确运行。同时,这也是一种提高软件并发性能和可维护性的基础...
首先,理解临界区的概念是关键。临界区是一种同步原语,通过定义一个代码段,当一个线程正在执行该代码段时,其他试图进入的线程会被挂起,直到第一个线程完成并离开。这样可以防止多个线程同时修改同一数据,确保...
在Windows中,临界区通过`EnterCriticalSection`和`LeaveCriticalSection`函数来进入和退出临界区;而在POSIX线程库pthread中,临界区则通过`pthread_mutex_lock`和`pthread_mutex_unlock`来实现。 在Win32 API中,...
首先,让我们理解临界区的概念。临界区通过使用特定的同步原语(如互斥量、信号量或事件)来实现。在C++中,我们可以使用`#include <windows.h>`引入Windows API,然后定义一个`CRITICAL_SECTION`结构体来表示临界区...
3. **使用临界区进行同步**:在VC++中,可以使用`CRITICAL_SECTION`结构体来定义临界区,并通过`InitializeCriticalSection`初始化,`EnterCriticalSection`和`LeaveCriticalSection`来管理。这样可以确保同一时间...
在实际使用时,可以根据需求选择事件、互斥量或临界区进行同步,并在代码中适当的位置调用`WaitForSingleObject`或`EnterCriticalSection`等函数来确保线程安全。 总结来说,临界区的互斥控制是多线程编程中防止...
本文将重点介绍三种常见的同步机制:临界区、互斥量和信号量,并通过示例代码帮助理解它们的工作原理及应用场景。 #### 二、临界区(Critical Section) 临界区是最简单的线程同步方式之一,适用于同一进程中的...
在Windows操作系统中,我们可以使用API函数如`EnterCriticalSection`和`LeaveCriticalSection`来实现临界区。而在C++中,我们可以使用互斥量(mutex)或者C++11标准库中的`std::mutex`来实现类似的功能。 下面是一...
如果已有其他线程在临界区内,调用`EnterCriticalSection`的线程会被挂起,直到其他线程退出临界区。 3. **离开临界区**: 当线程完成其任务并准备离开临界区时,使用`LeaveCriticalSection`函数。这将释放临界区,...
- `EnterCriticalSection`:进入临界区,阻止其他线程进入。 - `LeaveCriticalSection`:离开临界区,允许其他线程进入。 - `DeleteCriticalSection`:删除临界区结构体,释放资源。 ### 内核对象 - 事件(Event...
例如,我们创建一个对话框类`CriticalSectionDlg`,在这个类中我们可以定义临界区对象,然后在需要保护的代码段前后分别调用`EnterCriticalSection`和`LeaveCriticalSection`。 以下是一个简单的示例: ```cpp #...