线程同步之读写锁(锁操作的补充)

轻量级的读写锁(Slim Reader-Writer locks):读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。
这种锁相对于自旋锁而言,能提高并发性,因为在多处理器系统中,它允许同时有多个读者来访问共享资源,最大可能的读者数为实际的逻辑CPU数。
写者是排他性的,一个读写锁同时只能有一个写者或多个读者(与CPU数相关),但不能同时既有读者又有写者。

读写锁比起mutex具有更高的适用性,具有更高的并行性,可以有多个线程同时占用读模式的读写锁,但是只能有一个线程占用写模式的读写锁,读写锁的三种状态:
1.当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞
2.当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是以写模式对它进行加锁的线程将会被阻塞
3.当读写锁在读模式的锁状态时,如果有另外的线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁的请求,这样可以避免读模式锁长期占用,而等待的写模式锁请求则长期阻塞。

SRW代表-------Slim Reader-Writer

函数解析:

1.// 初始化读写锁
VOID WINAPI InitializeSRWLock
(
  __out PSRWLOCK SRWLock
);
函数功能:初始化读写锁


2.// 独占式访问
VOID WINAPI AcquireSRWLockExclusive

(
  __inout PSRWLOCK SRWLock
);
函数功能:写入者线程申请写资源。


3.// 独占式释放
VOID WINAPI ReleaseSRWLockExclusive

(
  __inout PSRWLOCK SRWLock
);
函数功能:写入者线程写资源完毕,释放对资源的占用。


4.// 共享式访问
VOID WINAPI AcquireSRWLockShared

(
  __inout PSRWLOCK SRWLock
);
函数功能:读取者线程申请读资源。

5.// 共享式释放
VOID WINAPI ReleaseSRWLockShared

(
  __inout PSRWLOCK SRWLock
);
函数功能:读取者线程结束读取资源,释放对资源的占用。

注意点:
1.访问方式只能选择其一,不可以同时使用。即一个线程仅能锁定资源一次,不能多次锁定资源。
2.读写锁声明后要初始化,但不用销毁,系统会自动清理读写锁。
3.读取者和写入者分别调用不同的申请函数和释放函数。

区别:
1.AcquireSRWLockExclusive抢占式的,当线程上锁后,其他线程无法进行访问。直到 ReleaseSRWLockExclusive,释放后。一般用于写操作。
2.AcquireSRWLockShared 是共享式的,即使线程上锁后,其他线程也可以进行再次访问。一般用于读操作。

 

 

源代码:
// Semaphore.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <Windows.h>
#include <process.h>

//线程数
#define  g_nThreadNum 3

//信号量
SRWLOCK g_srwLock;

//累加数
int g_nCount = 50;

unsigned _stdcall WriteThread(void * lParam)
{
    
    // 独占式访问
    AcquireSRWLockExclusive(&g_srwLock);
    
    g_nCount++;
    
    // 独占式释放
    ReleaseSRWLockExclusive(&g_srwLock);
    
    return 0;
}

unsigned _stdcall ReadThread(void *lParam)
{
    // 共享式访问
    AcquireSRWLockShared(&g_srwLock);
    
    printf("g_nCount=%d\n", g_nCount);
    
    // 共享式释放
    ReleaseSRWLockShared(&g_srwLock);

    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    //// 初始化读写锁
    InitializeSRWLock(&g_srwLock);
    //启动线程
    HANDLE pThread[g_nThreadNum];
    
    pThread[0] = (HANDLE)_beginthreadex(NULL, 0, ReadThread, NULL, 0, 0);
    
    pThread[1] = (HANDLE)_beginthreadex(NULL, 0, WriteThread, NULL, 0, 0);

    pThread[2] = (HANDLE)_beginthreadex(NULL, 0, ReadThread, NULL, 0, 0);
    
    //等待线程结束
    WaitForMultipleObjects(g_nThreadNum, pThread, TRUE, INFINITE);

    printf("g_nCount:%d\n", g_nCount);

    //释放资源
    for (int i = 0; i < g_nThreadNum; ++i)
    {
        CloseHandle(pThread[i]);
    }
    
    getchar();
    return 0;
}

 

posted @ 2017-10-19 18:39  gd_沐辰  阅读(795)  评论(0编辑  收藏  举报