第二篇 多线程之临界区

临界区


临界区指的是一个访问共用资源(共用设备或共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性。当有线程进入临界区段时,其他线程或是进程必须等待,有一些同步的机制必须在临界区段的进入点与离开点实现,以确保这些共用资源是被互斥获得使用。


用法

临界区在使用时以CRITICAL_SECTION结构对象保护共享资源,并分别用EnterCriticalSection()和LeaveCriticalSection()函数去标识和释放一个临界区。所用到的CRITICAL_SECTION结构对象必须经过InitializeCriticalSection()的初始化后才能使用,而且必须确保所有线程中的任何试图访问此共享资源的代码都处在此临界区的保护之下。否则临界区将不会起到应有的作用,共享资源依然有被破坏的可能。

typedef struct _CRITICAL_SECTION {
	PCRITICAL_SECTION_DEBUG DebugInfo;//用于调试
	LONG LockCount;//初始化为-1 表示有LockCount个线程在等待
	LONG RecursionCount;//表示该临界区的拥有线程对此资源获得临界区次数,初为0
	HANDLE OwningThread;//拥有此临界区的线程句柄
	HANDLE LockSemaphore;//信号量 是一个自复位事件
	DWORD SpinCount;//旋转锁的设置,单CPU下忽略,旋转次数一般设置为4000
} CRITICAL_SECTION,*PCRITICAL_SECTION,*LPCRITICAL_SECTION;

解决多线程同步的问题

问题描述:在多个线程访问同一个资源的时候,我们需要对资源同步访问,假设我们的资源为X

#include <iostream>
#include <windows.h>
#include <windef.h>
#include <process.h>
using namespace std;

#define THREAD_NUM 20

int X;//资源
HANDLE hand[THREAD_NUM];

void fun(void *p)
{
    int *x=static_cast<int*>(p);

    ++X;

    cout<<"current dev:"<<*x<<" access to X:"<<X<<endl;
}


int main()
{
    X=0;
    for(int i=0;i<THREAD_NUM;i++)
    {
        hand[i]= (HANDLE)_beginthread(fun,0,&i);
    }
    WaitForMultipleObjects(THREAD_NUM,hand,TRUE,INFINITE);

    return 0;
}

得到的结果如下:

current dev:current dev:5 access to X:3current dev:15 access to X:6
current dev:20 access to X:19

current dev:20 access to X:12
5 access to X:2
current dev:20 access to X:18
current dev:20 access to X:9
current dev:18 access to X:7
current dev:3 access to X:1
current dev:20 access to X:10
current dev:20 access to X:15
current dev:20 access to X:20
current dev:20 access to X:16
current dev:20 access to X:11
current dev:7 access to X:4
current dev:20 access to X:8
current dev:11 access to X:5
current dev:20 access to X:current dev:current dev:20 access to X:13
1420 access to X:17

Process returned 0 (0x0)   execution time : 0.316 s

//由于资源抢占 所以为不确定结果

为了解决资源的同步访问我们用临界区来解决这个问题

#include <iostream>
#include <windows.h>
#include <windef.h>
#include <process.h>
using namespace std;

#define THREAD_NUM 20

int X;//资源
HANDLE hand[THREAD_NUM];
CRITICAL_SECTION section;
void fun(void *p)
{
    int *x=static_cast<int*>(p);
    EnterCriticalSection(&section);
    ++X;

    cout<<"current dev:"<<*x<<" access to X:"<<X<<endl;
    LeaveCriticalSection(&section);
}


int main()
{
    X=0;
    InitializeCriticalSection(&section);
    for(int i=0;i<THREAD_NUM;i++)
    {
        hand[i]= (HANDLE)_beginthread(fun,0,&i);
    }
    WaitForMultipleObjects(THREAD_NUM,hand,TRUE,INFINITE);
    DeleteCriticalSection(&section);
    return 0;
}

得到结果如下:

current dev:3 access to X:1
current dev:20 access to X:2
current dev:20 access to X:3
current dev:20 access to X:4
current dev:20 access to X:5
current dev:20 access to X:6
current dev:20 access to X:7
current dev:20 access to X:8
current dev:20 access to X:9
current dev:20 access to X:10
current dev:20 access to X:11
current dev:20 access to X:12
current dev:20 access to X:13
current dev:20 access to X:14
current dev:20 access to X:15
current dev:20 access to X:16
current dev:20 access to X:17
current dev:20 access to X:18
current dev:20 access to X:19
current dev:20 access to X:20

Process returned 0 (0x0)   execution time : 0.215 s
//可以发现资源X同步了

然后我们尝试同步的去访问资源

#include <iostream>
#include <windows.h>
#include <windef.h>
#include <process.h>
using namespace std;

#define THREAD_NUM 20

int X;//资源
HANDLE hand[THREAD_NUM];
CRITICAL_SECTION section;
CRITICAL_SECTION section_i;
void fun(void *p)
{
    int *x=static_cast<int*>(p);
    EnterCriticalSection(&section);
    ++X;

    cout<<"current dev:"<<*x<<" access to X:"<<X<<endl;
    LeaveCriticalSection(&section);
    LeaveCriticalSection(&section_i);
}


int main()
{
    X=0;
    InitializeCriticalSection(&section);
    InitializeCriticalSection(&section_i);
    for(int i=0;i<THREAD_NUM;i++)
    {
        EnterCriticalSection(&section_i);
        hand[i]= (HANDLE)_beginthread(fun,0,&i);
    }
    WaitForMultipleObjects(THREAD_NUM,hand,TRUE,INFINITE);
    DeleteCriticalSection(&section);
    DeleteCriticalSection(&section_i);
    return 0;
}

然而结果和上面的到的结果是一样的,我们回头看看对临界区的定义发现他只是防止线程同时调用资源,也就是说线程之间是互斥的访问资源的,但是无法解决线程的同步问题,也就是说实现了资源的同步访问,但是无法实现同步的访问资源,那么怎么才能同步的访问资源呢,且听下回分析。

 

转载于:https://my.oschina.net/pirtt/blog/702981

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值