1.简介
SRWLOCK的目的和关键段相同:对一个资源进行保护,不让其他线程访问它。但是,与关键段不同的是,SRWLOCK允许我们区分那些想要读取资源的值的线程和想要更新资源的值的线程。让所有的读取者线程在同一时刻访问共享资源应该是可行的,因为仅仅读取资源的值并不存在破坏数据的风险。
首先需要分配一个SRWLOCK结构,并用InitializeSRWLock初始化。
void InitializeSRWLock(
[out] PSRWLOCK SRWLock
);
一旦初始化完成之后,写入者线程可以调用AcquireSRWLockExclusive(&lock),以尝试获得对 被保护的资源的独占访问权。
void AcquireSRWLockExclusive(
[in, out] PSRWLOCK SRWLock
);
完成对资源的更新之后,应该调用ReleaseSRWLockExclusive(&lock),解除对资源的锁定。
void ReleaseSRWLockExclusive(
[in, out] PSRWLOCK SRWLock
);
对于读取者线程来说,同样有两个步骤,但调用的是下面两个新的函数。
AcquireSRWLockShared(&lock);
ReleaseSRWLockShared(&lock);
不存在用来删除或销毁SRWLOCK的函数,系统会自动执行清理工作。
2.示例
创建三个线程,两个读,一个写。
// Interlocked.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <windows.h>
DWORD WINAPI read(LPVOID);
DWORD WINAPI write(LPVOID);
long g_sum = 10;
SRWLOCK lock;
int main()
{
HANDLE aThread[3];
DWORD ThreadID;
InitializeSRWLock(&lock);
//创建两个读线程,一个写线程
aThread[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)read, NULL, 0, &ThreadID);
if (aThread[0] == NULL)
{
printf("CreateThread error: %d\n", GetLastError());
return 1;
}
aThread[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)write, NULL, 0, &ThreadID);
if (aThread[1] == NULL)
{
printf("CreateThread error: %d\n", GetLastError());
return 1;
}
aThread[2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)read, NULL, 0, &ThreadID);
if (aThread[2] == NULL)
{
printf("CreateThread error: %d\n", GetLastError());
return 1;
}
WaitForMultipleObjects(3, aThread, TRUE, INFINITE);
// Close thread and mutex handles
for (int i = 0; i < 3; i++)
CloseHandle(aThread[i]);
return 0;
}
DWORD WINAPI read(LPVOID lpParam)
{
UNREFERENCED_PARAMETER(lpParam);
AcquireSRWLockShared(&lock);
printf("read Thread %d g_sum = %d\n",
GetCurrentThreadId(), g_sum);
ReleaseSRWLockShared(&lock);
return g_sum;
}
DWORD WINAPI write(LPVOID lpParam)
{
UNREFERENCED_PARAMETER(lpParam);
AcquireSRWLockExclusive(&lock);
g_sum++;
printf("write Thread %d g_sum = %d\n",
GetCurrentThreadId(), g_sum);
ReleaseSRWLockExclusive(&lock);
return g_sum;
}