用户模式下的线程同步——Slim读/写锁

SRWLock的目的和关键段一样,但不同的是SRWLock可以区分哪些线程要读取共享资源,哪些要更新共享资源。读取共享资源的线程因为不会破坏共享资源的数据,故这些线程可以同时读取同一共享资源,但要更新共享资源的线程必须独占共享资源,此时读取线程也没有权限访问共享资源。

更新线程:
1.定义一个SRWLOCk结构,并用InitializeSRWLock函数对它进行初始化:

VOID InitializeSRWLock(PSRWLOCK SRWLock);

2.初始化后,写入者线程可以调用AcquireSRWLockExclusive,尝试获得被保护资源的独占权:

VOID AcquireSRWLockExclusive(PSRWLOCK SRWLock);

3.完成对资源的更新后,解除对资源的锁定

VOID ReleaseSRWLockExclusive(PSRWLOCK SRWLock);

读取线程
和读取线程基本类似,除了以下俩个函数

VOID AcquireSRWLockShared(PSRWLOCK SRWLock);
VOID ReleaseSRWLockShared(PSRWLOCK SRWLock);

SRWLOCk不用删除或销毁,系统会自动执行清理工作。

#include "stdafx.h"
#include <windows.h>          
#include <process.h> 
#include <iostream>

using namespace std;

int g_x = 0;
SRWLOCK g_srwLock;

UINT WINAPI WriteThreadFunc1(PVOID pArguments)
{
    AcquireSRWLockExclusive(&g_srwLock);
    int n = 0;
    while (n < 3)
    {
        g_x += n;
        n++;
        cout << "WriteThreadFunc1.." << endl;
    }
    ReleaseSRWLockExclusive(&g_srwLock);
    _endthreadex(0);
    return 0;
}
UINT WINAPI WriteThreadFunc2(PVOID pArguments)
{
    AcquireSRWLockExclusive(&g_srwLock);
    int n = 0;
    while (n < 5)
    {
        g_x += n;
        n++;
        cout << "WriteThreadFunc2.." << endl;
    }
    ReleaseSRWLockExclusive(&g_srwLock);
    _endthreadex(0);
    return 0;
}
UINT WINAPI ReadThreadFunc1(PVOID pArguments)
{
    AcquireSRWLockShared(&g_srwLock);
    cout << "ReadThreadFunc1.." << endl;
    ReleaseSRWLockShared(&g_srwLock);
    _endthreadex(0);
    return 0;
}
UINT WINAPI ReadThreadFunc2(PVOID pArguments)
{
    AcquireSRWLockShared(&g_srwLock);
    cout << "ReadThreadFunc2.." << endl;
    ReleaseSRWLockShared(&g_srwLock);
    _endthreadex(0);
    return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE   handle1, handle2, handle3, handle4;
    unsigned  unThread1ID, unThread2ID;

    cout << "g_x initial value: " << g_x << endl;
    InitializeSRWLock(&g_srwLock);
    handle1 = (HANDLE)_beginthreadex(NULL,
        0,
        &WriteThreadFunc1,
        NULL,
        0,
        &unThread1ID);
    handle2 = (HANDLE)_beginthreadex(NULL,
        0,
        &WriteThreadFunc2,
        NULL,
        0,
        &unThread2ID);
    handle3 = (HANDLE)_beginthreadex(NULL,
        0,
        &ReadThreadFunc1,
        NULL,
        0,
        &unThread1ID);
    handle4 = (HANDLE)_beginthreadex(NULL,
        0,
        &ReadThreadFunc2,
        NULL,
        0,
        &unThread2ID);
    WaitForSingleObject(handle1, INFINITE);
    WaitForSingleObject(handle2, INFINITE);
    WaitForSingleObject(handle3, INFINITE);
    WaitForSingleObject(handle4, INFINITE);
    cout << "g_x Final value: " << g_x << endl;
    getchar();
    return 0;
}

输出结果有时是这样的:

WriteThreadFunc1..
WriteThreadFunc1..
WriteThreadFunc1..
WriteThreadFunc2..
WriteThreadFunc2..
WriteThreadFunc2..
WriteThreadFunc2..
WriteThreadFunc2..
ReadThreadFunc1..ReadThreadFunc2..

写线程的输出很好理解,因为他们独占资源,所以写线程不可能并发运行,而是一个一个执行的。
那有人问了我的输出不是这样啊?也有可能是下面三种情况

ReadThreadFunc2..ReadThreadFunc1..
ReadThreadFunc1..
ReadThreadFunc2..
ReadThreadFunc2..
ReadThreadFunc1..

其实很好理解,读线程可以在同一时刻访问共享资源。所以当写线程执行完后,俩个读线程同时结束等待状态,变成是可调度状态,系统可能会先执行ReadThreadFunc1,然后在执行ReadThreadFunc2,或者反之,这样就出现了下面俩种输出结果:

ReadThreadFunc1..
ReadThreadFunc2..
ReadThreadFunc2..
ReadThreadFunc1..

也有可能ReadThreadFunc1执行到cout << “ReadThreadFunc1..”到这步, 然后ReadThreadFunc1被暂停,系统切换到ReadThreadFunc2(ReadThreadFunc1和ReadThreadFunc2顺序可调换)。这样就出现了下面俩种输出结果:

ReadThreadFunc1..ReadThreadFunc2..
ReadThreadFunc2..ReadThreadFunc1..
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值