Slim读写锁简称SRWLock,它的目的和临界区相同,对一个资源进行保护,不让其他线程访问。但是不同的是SRWLock允许我们区分哪些线程是读取共享资源的值,哪些线程是修改共享资源的值。所有读线程在同一时刻可以访问共享资源,因为这些线程不会破坏共享资源,只有当写线程要访问共享资源时,才需要进行同步。写线程应当独占式访问资源,其他任何线程都不允许访问资源。这就是SRWLock提供的全部功能。
所以SRWLock的访问分为两种方式:
- 独占式访问:写线程访问共享资源的方式;
- 共享式访问:读线程访问共享资源的方式;
SRWLock需要通过一个SRWLOCK结构来进行实现;
要说明的是SRWLock的使用要求OS至少是Vista,在XP上不能使用。
读写锁对象使用要调用的函数接口如下:
(1)InitializeSRWLock()
- VOID WINAPI InitializeSRWLock(
- _Out_ PSRWLOCK SRWLock
- );
- //SRWLock:指向读写锁对象的指针;
在使用读写锁之前要先分配一个SRWLOCK结构,然后调用InitializeSRWLock函数进行读写锁结构的初始化。
(2)AcquireSRWLockExclusive()
- VOID WINAPI AcquireSRWLockExclusive(
- _Inout_ PSRWLOCK SRWLock
- );
- //SRWLock:指向读写锁对象的指针;
该函数是写线程独占式的获得对资源的访问权限。
SRWLock初始化完成后,写入在线程可以调用该函数独占式的访问共享资源。
(3)ReleaseSRWLockExclusive()
- VOID WINAPI ReleaseSRWLockExclusive(
- _Inout_ PSRWLOCK SRWLock
- );
- //SRWLock:指向读写锁对象的指针;
该函数是写线程释放共享资源。
写入线程在完成对共享资源的更新后,应该调用该函数解除对该共享资源的锁定。
(4)AcquireSRWLockShared()
- VOID WINAPI AcquireSRWLockShared(
- _Inout_ PSRWLOCK SRWLock
- );
- //SRWLock:指向读写锁对象的指针;
该函数是读线程共享式访问共享资源。多个读线程可以在同一时刻共享式的访问共享数据资源,这有效的提高的程序的性能。
(5)ReleaseSRWLockShared()
- VOID WINAPI ReleaseSRWLockShared(
- _Inout_ PSRWLOCK SRWLock
- );
- //SRWLock:指向读写锁对象的指针;
该函数是读线程释放对共享资源的共享占用。
下面是读写锁的测试代码:
- #include <iostream>
- #include <windows.h>
- #include <process.h>
- using namespace std;
- SRWLOCK srwTest;
- volatile int flag = 0;
- void ReadThread1(void *ptr)
- {
- AcquireSRWLockShared(&srwTest);
- for (int i = 0; i < 5; ++i)
- {
- Sleep(1000);
- cout<<"read thread 1: "<<flag<<endl;
- }
- ReleaseSRWLockShared(&srwTest);
- }
- void ReadThread2(void *ptr)
- {
- AcquireSRWLockShared(&srwTest);
- for (int i = 0; i < 5; ++i)
- {
- Sleep(1000);
- cout<<"read thread 2: "<<flag<<endl;
- }
- ReleaseSRWLockShared(&srwTest);
- }
- void ReadThread3(void *ptr)
- {
- AcquireSRWLockShared(&srwTest);
- for (int i = 0; i < 5; ++i)
- {
- Sleep(1000);
- cout<<"read thread 3: "<<flag<<endl;
- }
- ReleaseSRWLockShared(&srwTest);
- }
- void WriteThread1(void *ptr)
- {
- AcquireSRWLockExclusive(&srwTest);
- flag = 1;
- for (int i = 0; i < 5; ++i)
- {
- Sleep(1000);
- cout<<"write thread 1: "<<flag<<endl;
- }
- ReleaseSRWLockExclusive(&srwTest);
- }
- void WriteThread2(void *ptr)
- {
- AcquireSRWLockExclusive(&srwTest);
- flag = 2;
- for (int i = 0; i < 5; ++i)
- {
- Sleep(1000);
- cout<<"write thread 2: "<<flag<<endl;
- }
- ReleaseSRWLockExclusive(&srwTest);
- }
- int main()
- {
- InitializeSRWLock(&srwTest);
- _beginthread(ReadThread1, 0, NULL);
- _beginthread(ReadThread2, 0, NULL);
- _beginthread(WriteThread1, 0, NULL);
- _beginthread(WriteThread2, 0, NULL);
- _beginthread(ReadThread3, 0, NULL);
- Sleep(INFINITE);
- }
程序的运行结果如下:
- read thread 2: 0
- read thread 1: 0
- read thread 2: 0
- read thread 1: 0
- read thread 2: 0
- read thread 1: 0
- read thread 2: 0
- read thread 1: 0
- read thread 2: 0
- read thread 1: 0
- write thread 1: 1
- write thread 1: 1
- write thread 1: 1
- write thread 1: 1
- write thread 1: 1
- write thread 2: 2
- write thread 2: 2
- write thread 2: 2
- write thread 2: 2
- write thread 2: 2
- read thread 3: 2
- read thread 3: 2
- read thread 3: 2
- read thread 3: 2
- read thread 3: 2
从结果可以看出ReadThread1和ReadThread2两个读线程可以同时访问共享资源,然后WriteThread1和WriteThread2请求独占式访问共享资源,但由于有读线程在访问共享资源,所以,这两个写线程会被挂起,直到所有的读线程结束访问。这里有个问题就是:如果写线程被阻塞期间不断的有读线程请求共享式访问共享资源,到底该不该予以访问权限呢,通过上面的代码ReadThread3测试可知,系统不会授予访问权限,因为这样会出现读线程优先,导致写线程一直处于阻塞的不公平状况。