Windows临界区初探

发布于:2023-01-04 ⋅ 阅读:(349) ⋅ 点赞:(0)

多线程冲突

一个进程的多个线程之间是可以共享进程的资源,比如代码段、堆空间、数据段、打开的文件等资源,当多个线程竞争共享资源,如果不采取有效的措施,则会造成共享数据的混乱。

以下代码创建两个线程,它们分别对共享变量 i 自增 1 执行 1000 次

#include <iostream>
#include <thread>

using namespace std;

int num = 0;

void test()
{
	for (int j = 0; j < 1000; j++) {
		num++;
	}
}
int main()
{
	cout << "Start two threads." << endl;

	thread thread_test1(test);
	thread thread_test2(test);

	thread_test1.join();
	thread_test2.join();

	cout << "two thread joined." << endl;

	cout << "Now num is " << num << endl;

	return 0;
}

控制台输出

Start two threads.
two thread joined.
Now num is 1543
Start two threads.
two thread joined.
Now num is 2000

可见,每次运行结果不一定为2000

临界区

由于多线程执行操作临界资源的这段代码可能会导致竞争状态,因此此段代码称为临界区。

Windows中临界区涉及四个关键函数:

#include <string>
#include <iostream>
#include <process.h>
#include <windows.h>

using namespace std;

//定义一个临界区
CRITICAL_SECTION g_cs;

int num = 0;

//线程绑定的函数返回值和参数是确定的,而且一定要__stdcall
unsigned __stdcall test(void* param)
{
    EnterCriticalSection(&g_cs);//进入临界区,如果有其他线程则等待
    for (int j = 0; j < 1000; j++) {
        num++;
    }
    cout << *(string*)(param) << endl;
    LeaveCriticalSection(&g_cs);//退出临界区,其他线程可以进来了
    return 1;
}


int main()
{
    //初始化临界区
    InitializeCriticalSection(&g_cs);

    HANDLE hth1, hth2, hth3;
    string s1 = "first", s2 = "second";

    //创建线程
    hth1 = (HANDLE)_beginthreadex(NULL, 0, test, &s1, 0, NULL);
    hth2 = (HANDLE)_beginthreadex(NULL, 0, test, &s2, 0, NULL);

    //等待子线程结束
    WaitForSingleObject(hth1, INFINITE);
    WaitForSingleObject(hth2, INFINITE);

    //一定要记得关闭线程句柄
    CloseHandle(hth1);
    CloseHandle(hth2);

    cout << "Now num is " << num << endl;

    //删除临界区
    DeleteCriticalSection(&g_cs);
}

输出结果

second
first
Now num is 2000
本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到