当多个线程对同一个数据进行读写的时候,如果这时候线程1对数据进行读取,而线程2在修改该数据,那么就会出现无法预料的结果。所以这时候就需要线程同步。
线程同步之临界区:
临界区是一段不会被中断的代码,多个线程只能有一个线程在临界区中。如果一个线程要进入临界区,而临界区中有其他线程,那么该线程会被挂起,直到临界区中的线程离开。
示例代码:
#include "stdafx.h"
#include<iostream>
#include<process.h>
#include<Windows.h>
using namespace std;
CRITICAL_SECTION cs; //声明临界区
void TestThread1(void* pvoid)
{
EnterCriticalSection(&cs); //进入临界区
cout << "线程1进去临界区\n";
Sleep(2000);
LeaveCriticalSection(&cs); //离开临界区
cout << "线程1离开临界区\n";
_endthread();
}
void TestThread2(void* pvoid)
{
EnterCriticalSection(&cs); //进入临界区
cout << "线程2进去临界区\n";
LeaveCriticalSection(&cs); //离开临界区
cout << "线程2离开临界区\n";
_endthread();
}
void TestThread3(void* pvoid)
{
EnterCriticalSection(&cs); //进入临界区
cout << "线程3进去临界区\n";
LeaveCriticalSection(&cs); //离开临界区
cout << "线程3离开临界区\n";
_endthread();
}
void Test()
{
InitializeCriticalSection(&cs); //初始化临界区
cout << "线程1起\n";
_beginthread(TestThread1, 0, nullptr);
Sleep(100); // 保证TestThread1先进入临界区
cout << "线程2起\n";
_beginthread(TestThread2, 0, nullptr);
cout << "线程3起\n";
_beginthread(TestThread3, 0, nullptr);
}
int _tmain(int argc, _TCHAR* argv[])
{
Test();
while (1)
{
Sleep(100);
}
DeleteCriticalSection(&cs); //不需要的时候删除临界区
system("pause");
return 0;
}
输出结果:
从输出这可以看出,线程1先进入临界区,这时候线程2和线程3都起了,都要进入临界区,但临界区中线程1在执行,所以线程2和线程3都被挂起,直到线程1离开临界区之后,线程2才进入临界区
ps1:如果在主线程中使用临界区需要非常注意,如果子线程在临界区停留太久,那主线程就会阻塞很久。
ps2:临界区同步只局限于在于同一个进程中使用,如果在不同进程中共享数据,那么就不能使用临界区了。