启动一个打印线程
#include <iostream>
#include <windows.h>
DWORD f(LPVOID para)
{
for(int i= 1;i<=100;i++)
cout<<i<<endl;
return 0;
}
int main
{
HANDLE thread1 = CreateThread(NULL, 0, f, NULL, 0, NULL);
// 等待线程结束
WaitForSingleObject(thread1, INFINITE);
CloseHandle(thread1);
}
临界区
每个进程中访问临界资源的那段代码称为临界区(Critical Section)(临界资源是一次仅允许一个进程使用的共享资源)。每次只准许一个进程进入临界区,进入后不允许其他进程进入。不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。
进程进入临界区的调度原则是:
- 如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。
- 任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。
- 进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。
- 如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。
临界区在使用时以CRITICAL_SECTION
结构对象保护共享资源,并分别用EnterCriticalSection()
和LeaveCriticalSection()
函数去标识和释放一个临界区。所用到的CRITICAL_SECTION
结构对象必须经过InitializeCriticalSection()
的初始化后才能使用,而且必须确保所有线程中的任何试图访问此共享资源的代码都处在此临界区的保护之下。否则临界区将不会起到应有的作用,共享资源依然有被破坏的可能。
在这段程序中我们访问共享资源s[10]
,并对它赋值。如果没有临界区的保护,则它会被赋值为随机的cacaac
交错。如果有这临界保护,这要么为全a,要么为全c。
临界区保护了一段代码,使得这段代码能一直执行完毕而不被其他线程争用。
#include <windows.h>
#include <iostream>
using namespace std;
// 定义临界区
CRITICAL_SECTION g_criticalSection;
char s[10];
struct Node{
char c ;
};
// 初始化临界区
void InitializeCriticalSection() {
InitializeCriticalSection(&g_criticalSection);
}
// 销毁临界区
void CleanupCriticalSection() {
DeleteCriticalSection(&g_criticalSection);
}
// 在临界区中执行操作
void PerformCriticalSectionOperation(char c) {
EnterCriticalSection(&g_criticalSection); //标识临界区
// 在这里执行需要互斥访问的操作
for(int i = 0;i<10;i++)
{
s[i] = c;
Sleep(1);
}
LeaveCriticalSection(&g_criticalSection); //释放临界区
}
DWORD lThread(LPVOID node)
{
Node *para = (Node*)node;
PerformCriticalSectionOperation(para->c);
return 0;
}
void test()
{
InitializeCriticalSection();
Node *node1 = new Node{'a'};
Node *node2 = new Node{'c'};
HANDLE thread1 = CreateThread(NULL, 0, lThread, node1, 0, NULL);
HANDLE thread2 = CreateThread(NULL, 0, lThread, node2, 0, NULL);
WaitForSingleObject(thread1, INFINITE);
WaitForSingleObject(thread2, INFINITE);
CloseHandle(thread1);
CloseHandle(thread2);
delete(node1);
delete(node2);
CleanupCriticalSection();
for(int i = 0;i<10;i++)
cout<<s[i]<<' ';
}
int main()
{
test();
return 0;
}
在C++中,EnterCriticalSection函数用于进入一个临界区,并锁定该临界区,防止其他线程进入临界区。如果EnterCriticalSection函数出错,可能有以下几个原因:
- 未初始化临界区:在调用EnterCriticalSection之前,应先通过InitializeCriticalSection函数对临界区进行初始化。
- 重复进入临界区:如果一个线程已经进入了临界区,并且没有释放锁定,再次调用EnterCriticalSection函数会导致错误。
- 线程安全问题:如果多个线程同时尝试进入临界区,可能会导致竞争条件和死锁。 线程终止:如果进入临界区的线程
- 在临界区内终止,可能会导致其他线程无法正常进入临界区。
- 内存不足:如果系统内存不足,可能导致EnterCriticalSection函数出错。 程序逻辑错误:
- 如果在调用EnterCriticalSection函数之前没有正确处理相关的条件或变量,可能会导致函数出错。